অ্যান্ড্রয়েড ২ডি রেন্ডারিং পাইপলাইন হার্ডওয়্যার অ্যাক্সিলারেশন সমর্থন করে, যার অর্থ হলো ক্যানভাসে সম্পাদিত সমস্ত ড্রয়িং অপারেশন জিপিইউ ব্যবহার করে। হার্ডওয়্যার অ্যাক্সিলারেশন সক্রিয় করার জন্য প্রয়োজনীয় বর্ধিত রিসোর্সের কারণে, আপনার অ্যাপ আরও বেশি র্যাম ব্যবহার করবে।
হার্ডওয়্যার অ্যাক্সিলারেশন ডিফল্টরূপে সক্রিয় থাকে। যদি আপনার অ্যাপ্লিকেশনটি শুধুমাত্র স্ট্যান্ডার্ড কম্পোজেবল ব্যবহার করে, তবে এটিকে বিশ্বব্যাপী চালু করলে ড্রয়িং-এর উপর কোনো বিরূপ প্রভাব পড়ার কথা নয়। তবে, যেহেতু সমস্ত ২ডি ড্রয়িং অপারেশনের জন্য হার্ডওয়্যার অ্যাক্সিলারেশন সমর্থিত নয়, তাই এটি চালু করলে আপনার কিছু কাস্টম ড্রয়িং কল প্রভাবিত হতে পারে। সমস্যাগুলো সাধারণত অদৃশ্য এলিমেন্ট, এক্সেপশন, বা ভুলভাবে রেন্ডার হওয়া পিক্সেল হিসাবে প্রকাশ পায়। এর প্রতিকারের জন্য, অ্যান্ড্রয়েড আপনাকে একাধিক স্তরে হার্ডওয়্যার অ্যাক্সিলারেশন সক্রিয় বা নিষ্ক্রিয় করার বিকল্প দেয়। হার্ডওয়্যার অ্যাক্সিলারেশন নিয়ন্ত্রণ দেখুন।
আপনার অ্যাপ্লিকেশনটি যদি কাস্টম ড্রয়িং করে, তবে কোনো সমস্যা খুঁজে বের করার জন্য হার্ডওয়্যার অ্যাক্সিলারেশন চালু থাকা অবস্থায় আসল হার্ডওয়্যার ডিভাইসে অ্যাপ্লিকেশনটি পরীক্ষা করুন। ‘ড্রয়িং অপারেশনের জন্য সাপোর্ট’ বিভাগে হার্ডওয়্যার অ্যাক্সিলারেশনের পরিচিত সমস্যা এবং সেগুলো সমাধানের উপায় বর্ণনা করা হয়েছে।
এছাড়াও ফ্রেমওয়ার্ক এপিআই সহ ওপেনজিএল দেখুন।
হার্ডওয়্যার ত্বরণ নিয়ন্ত্রণ করুন
আপনি নিম্নলিখিত স্তরগুলিতে হার্ডওয়্যার অ্যাক্সিলারেশন নিয়ন্ত্রণ করতে পারেন:
- আবেদন
- কার্যকলাপ
- জানালা
- রচনাযোগ্য
অ্যাপ্লিকেশন স্তর
আপনার সম্পূর্ণ অ্যাপ্লিকেশনের জন্য হার্ডওয়্যার অ্যাক্সিলারেশন সক্রিয় করতে, আপনার অ্যান্ড্রয়েড ম্যানিফেস্ট ফাইলে <application> ট্যাগে নিম্নলিখিত অ্যাট্রিবিউটটি যোগ করুন:
<application android:hardwareAccelerated="true" ...>
কার্যকলাপের স্তর
যদি আপনার অ্যাপ্লিকেশনটি বিশ্বব্যাপী হার্ডওয়্যার অ্যাক্সিলারেশন চালু থাকা অবস্থায় সঠিকভাবে কাজ না করে, তবে আপনি এটিকে স্বতন্ত্র অ্যাক্টিভিটিগুলোর জন্যও নিয়ন্ত্রণ করতে পারেন। অ্যাক্টিভিটি পর্যায়ে হার্ডওয়্যার অ্যাক্সিলারেশন চালু বা বন্ধ করতে, আপনি <activity> এলিমেন্টের জন্য android:hardwareAccelerated অ্যাট্রিবিউটটি ব্যবহার করতে পারেন। নিচের উদাহরণটি সম্পূর্ণ অ্যাপ্লিকেশনের জন্য হার্ডওয়্যার অ্যাক্সিলারেশন চালু করে কিন্তু একটি অ্যাক্টিভিটির জন্য তা বন্ধ করে দেয়:
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
জানালার স্তর
আপনার যদি আরও সূক্ষ্ম নিয়ন্ত্রণের প্রয়োজন হয়, তাহলে নিম্নলিখিত কোডটি ব্যবহার করে একটি নির্দিষ্ট উইন্ডোর জন্য হার্ডওয়্যার অ্যাক্সিলারেশন সক্রিয় করতে পারেন:
window.setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
)
রচনাযোগ্য স্তর
Compose-এ হার্ডওয়্যার অ্যাক্সিলারেশন নিষ্ক্রিয় করার জন্য প্রতিটি কম্পোজেবলের জন্য আলাদা কোনো সুইচ নেই।
একটি কম্পোজেবলকে তার নিজস্ব লেয়ারে রেন্ডার করতে Modifier.graphicsLayer ব্যবহার করুন। এটি কম্পোজেবলের ড্রয়িং কোড পুনরায় না চালিয়েই ট্রান্সফর্ম প্রোপার্টিগুলো (যেমন alpha , scaleX , scaleY , translationX , translationY , rotationX , rotationY , rotationZ , এবং transformOrigin ) পরিবর্তন করতে দেয়। সর্বোত্তম পারফরম্যান্সের জন্য, এই প্রোপার্টিগুলো সেট করতে সর্বদা মডিফায়ারের ল্যাম্বডা ফর্ম ব্যবহার করুন।
লেয়ারের মধ্যে কাস্টম ব্লেন্ডিং-এর মতো উন্নত ড্রয়িং অপারেশনের জন্য সুস্পষ্টভাবে একটি অফ-স্ক্রিন বাফার প্রয়োগ করতে, CompositingStrategy.Offscreen ব্যবহার করুন। আরও তথ্যের জন্য, গ্রাফিক্স মডিফায়ার্স দেখুন।
আপনার যদি এমন কোনো কাস্টম ড্রয়িং অপারেশন থাকে যার জন্য কঠোরভাবে সফটওয়্যার রেন্ডারিং প্রয়োজন, তাহলে আপনি AndroidView ব্যবহার করে একটি লিগ্যাসি ভিউ হোস্ট করতে পারেন এবং সেই ভিউতে setLayerType(View.LAYER_TYPE_SOFTWARE, null) কল করতে পারেন।
অঙ্কন কার্যক্রমের জন্য সহায়তা
হার্ডওয়্যার অ্যাক্সিলারেটেড হলে, ২ডি রেন্ডারিং পাইপলাইনটি সর্বাধিক ব্যবহৃত Canvas ড্রয়িং অপারেশনগুলোর পাশাপাশি অনেক কম ব্যবহৃত অপারেশনও সমর্থন করে। অ্যান্ড্রয়েডের সাথে আসা অ্যাপ্লিকেশনগুলো রেন্ডার করতে ব্যবহৃত সমস্ত ড্রয়িং অপারেশন, স্ট্যান্ডার্ড কম্পোজেবল এবং রিফ্লেকশন ও টাইল্ড টেক্সচারের মতো সাধারণ উন্নত ভিজ্যুয়াল ইফেক্টগুলো সমর্থিত।
নিম্নলিখিত সারণিতে এপিআই স্তর অনুযায়ী বিভিন্ন অপারেশনের সমর্থনের স্তর বর্ণনা করা হয়েছে:
| প্রথম সমর্থিত এপিআই স্তর | ||||
| ক্যানভাস | ||||
| drawBitmapMesh() (রঙের অ্যারে) | ১৮ | |||
| drawPicture() | ২৩ | |||
| drawPosText() | ১৬ | |||
| drawTextOnPath() | ১৬ | |||
| drawVertices() | ২৯ | |||
| setDrawFilter() | ১৬ | |||
| clipPath() | ১৮ | |||
| clipRegion() | ১৮ | |||
| clipRect(Region.Op.XOR) | ১৮ | |||
| clipRect(Region.Op.Difference) | ১৮ | |||
| clipRect(Region.Op.ReverseDifference) | ১৮ | |||
| ঘূর্ণন/প্রেক্ষিত সহ clipRect() | ১৮ | |||
| রঙ | ||||
| setAntiAlias() (টেক্সটের জন্য) | ১৮ | |||
| setAntiAlias() (লাইনগুলির জন্য) | ১৬ | |||
| setFilterBitmap() | ১৭ | |||
| setLinearText() | ✗ | |||
| setMaskFilter() | ✗ | |||
| setPathEffect() (লাইনগুলোর জন্য) | ২৮ | |||
| setShadowLayer() (টেক্সট ছাড়া) | ২৮ | |||
| setStrokeCap() (লাইনের জন্য) | ১৮ | |||
| setStrokeCap() (পয়েন্টের জন্য) | ১৯ | |||
| setSubpixelText() | ২৮ | |||
| Xfermode | ||||
| PorterDuff.Mode.DARKEN (ফ্রেমবাফার) | ২৮ | |||
| PorterDuff.Mode.LIGHTEN (ফ্রেমবাফার) | ২৮ | |||
| PorterDuff.Mode.OVERLAY (ফ্রেমবাফার) | ২৮ | |||
| শেডার | ||||
| ComposeShader এর ভিতরে ComposeShader | ২৮ | |||
| ComposeShader এর ভিতরে একই ধরণের শেডার | ২৮ | |||
| ComposeShader-এ স্থানীয় ম্যাট্রিক্স | ১৮ | |||
ক্যানভাস স্কেলিং
হার্ডওয়্যার অ্যাক্সিলারেটেড ২ডি রেন্ডারিং পাইপলাইনটি প্রাথমিকভাবে আনস্কেলড ড্রয়িং সমর্থন করার জন্য তৈরি করা হয়েছিল, যেখানে কিছু ড্রয়িং অপারেশন উচ্চতর স্কেল মানে গুণমানকে উল্লেখযোগ্যভাবে হ্রাস করত। এই অপারেশনগুলো GPU দ্বারা রূপান্তরিত, ১.০ স্কেলে আঁকা টেক্সচার হিসাবে প্রয়োগ করা হয়। API লেভেল ২৮ থেকে শুরু করে, সমস্ত ড্রয়িং অপারেশন কোনো সমস্যা ছাড়াই স্কেল করা যায়।
নিম্নোক্ত সারণিতে দেখানো হয়েছে কখন বৃহৎ পরিসর সঠিকভাবে সামাল দেওয়ার জন্য বাস্তবায়নে পরিবর্তন আনা হয়েছিল:
| অঙ্কন কার্যক্রমকে স্কেল করতে হবে | প্রথম সমর্থিত এপিআই স্তর |
| drawText() | ১৮ |
| drawPosText() | ২৮ |
| drawTextOnPath() | ২৮ |
| সরল আকার | ১৭ |
| জটিল আকার | ২৮ |
| drawPath() | ২৮ |
| ছায়া স্তর | ২৮ |
আপনার ব্যবহৃত কোনো ড্রয়িং অপারেশন যদি হার্ডওয়্যার অ্যাক্সিলারেটেড না হয়, তবে সংশ্লিষ্ট ড্রয়িংটিকে একটি অফ-স্ক্রিন সফটওয়্যার Bitmap (বা ImageBitmap )-এ রেন্ডার করুন এবং ফলাফলটি অঙ্কন করুন। আপনার UI-এর বাকি অংশ হার্ডওয়্যার-অ্যাক্সিলারেটেড পাথটিই বজায় রাখবে।
টিপস এবং কৌশল
হার্ডওয়্যার অ্যাক্সিলারেটেড ২ডি গ্রাফিক্সে পরিবর্তন করলে পারফরম্যান্স তাৎক্ষণিকভাবে বাড়তে পারে, কিন্তু তারপরেও আপনার অ্যাপ্লিকেশনটিকে এমনভাবে ডিজাইন করা উচিত যাতে এটি জিপিইউ-কে কার্যকরভাবে ব্যবহার করতে পারে। এর জন্য নিম্নলিখিত সুপারিশগুলো অনুসরণ করুন:
- লেআউটের জটিলতা এবং পুনর্গঠন হ্রাস করুন
- লেআউট ট্রি অগভীর রাখুন এবং রিকম্পোজের পরিমাণ সীমিত করুন। স্টেট রিডকে সবচেয়ে সংকীর্ণ পরিসরে স্থগিত করুন, যাতে কোনো পরিবর্তন ক্ষুদ্রতম সম্ভাব্য অঞ্চলকে রিড্র করে। উদাহরণস্বরূপ, কোনো কম্পোজেবলের বডির পরিবর্তে
Modifier.graphicsLayer { }এর ভিতরে অ্যানিমেটেড স্টেট রিড করুন। আরও তথ্যের জন্য, Jetpack Compose performance দেখুন। - অতিরিক্ত উত্তোলন এড়িয়ে চলুন
- একটির উপর আরেকটি করে অনেক বেশি লেয়ার আঁকবেন না। উপরের অন্য অস্বচ্ছ এলিমেন্টের কারণে সম্পূর্ণভাবে ঢাকা পড়ে যাওয়া যেকোনো UI এলিমেন্ট সরিয়ে ফেলুন। যদি আপনাকে একটির উপর আরেকটি মিশিয়ে একাধিক লেয়ার আঁকতে হয়, তবে সেগুলোকে একটিমাত্র লেয়ারে একীভূত করার কথা বিবেচনা করুন। বর্তমান হার্ডওয়্যারের ক্ষেত্রে একটি ভালো সাধারণ নিয়ম হলো, প্রতি ফ্রেমে স্ক্রিনের পিক্সেল সংখ্যার আড়াই গুণের বেশি না আঁকা (বিটম্যাপের স্বচ্ছ পিক্সেলগুলোও এর মধ্যে গণ্য হয়!)।
- ড্র মেথডে রেন্ডার অবজেক্ট তৈরি করবেন না।
- একটি সাধারণ ভুল হলো, প্রতিবার কোনো রেন্ডারিং মেথড কল করার সময় একটি নতুন
Paintবা নতুনPathতৈরি করা। এর ফলে গার্বেজ কালেক্টরকে আরও ঘন ঘন চলতে হয় এবং হার্ডওয়্যার পাইপলাইনে থাকা ক্যাশে ও অপটিমাইজেশনও বাইপাস হয়ে যায়। এটি এড়াতে, আপনার অবজেক্টগুলো পুনঃব্যবহার ও পরিবর্তন করুন:- প্রমিত পদ্ধতি ব্যবহার করুন : প্রমিত
DrawScopeপদ্ধতিগুলো (যেমনdrawRectএবংdrawCircle) ডেভেলপার অ্যালোকেশনের প্রয়োজন ছাড়াই অভ্যন্তরীণভাবেPaintঅবজেক্টগুলোকে পুনঃব্যবহার করে। - পুনরায় বরাদ্দ করার পরিবর্তে পরিবর্তন করুন : কাস্টম লজিক লেখার সময়, একটি নতুন
Pathইনস্ট্যানশিয়েট করার পরিবর্তে বিদ্যমানPathখালি করতেpath.rewindব্যবহার করুন। - দক্ষতার সাথে স্টেট ধরে রাখুন : একটি কম্পোজেবলের ভিতরে,
remember { Path() }ব্যবহার করে একবারই অবজেক্ট অ্যালোকেট করুন। আপনি যদি পুনঃব্যবহারযোগ্য কাস্টম মডিফায়ার এক্সটেনশন তৈরি করেন, তবে নতুন হিপ অ্যালোকেশন না ঘটিয়ে অবজেক্ট অ্যালোকেট ও পুনঃব্যবহার করার জন্যDrawModifierNodeব্যবহার করে একটি কাস্টমModifier.Nodeইমপ্লিমেন্ট করুন।
- প্রমিত পদ্ধতি ব্যবহার করুন : প্রমিত
- খুব ঘন ঘন আকৃতি পরিবর্তন করবেন না।
- উদাহরণস্বরূপ, জটিল আকার, পাথ এবং বৃত্ত টেক্সচার মাস্ক ব্যবহার করে রেন্ডার করা হয়। প্রতিবার যখন আপনি একটি পাথ তৈরি বা পরিবর্তন করেন, হার্ডওয়্যার পাইপলাইন একটি নতুন মাস্ক তৈরি করে, যা ব্যয়বহুল হতে পারে।
- বিটম্যাপ খুব ঘন ঘন পরিবর্তন করবেন না।
- প্রতিবার যখন আপনি একটি বিটম্যাপের বিষয়বস্তু পরিবর্তন করেন, পরবর্তীবার আঁকার সময় তা আবার একটি GPU টেক্সচার হিসেবে আপলোড হয়ে যায়।
- আলফা সাবধানে ব্যবহার করুন
- যখন আপনি
Modifier.alphaবা Compose অ্যানিমেশন API ব্যবহার করে একটি কম্পোজেবল ট্রান্সলুসেন্ট তৈরি করেন, তখন এটি সাধারণত একটি অফ-স্ক্রিন বাফারে রেন্ডার করা হয়, যা প্রয়োজনীয় ফিল-রেট দ্বিগুণ করে দেয়। ওভারল্যাপবিহীন কন্টেন্টের জন্য অফ-স্ক্রিন বাফারের অতিরিক্ত চাপ এড়াতে,CompositingStrategy.ModulateAlphaসেট করুন। স্বতন্ত্র ড্র কলগুলির জন্য, লেয়ার তৈরি না করেই সরাসরি ড্রয়িং কমান্ডে আলফা প্রয়োগ করুন (যেমনcolor = Color.Red.copy(alpha = 0.5f)ব্যবহার করে)।