1616
1717#define LOG_TAG " OpenGLRenderer"
1818
19- #include < SkCanvas.h>
20- #include < SkGradientShader.h>
21-
2219#include < utils/threads.h>
2320
2421#include " Debug.h"
2825namespace android {
2926namespace uirenderer {
3027
28+ // /////////////////////////////////////////////////////////////////////////////
29+ // Defines
30+ // /////////////////////////////////////////////////////////////////////////////
31+
32+ #define GRADIENT_TEXTURE_HEIGHT 2
33+ #define GRADIENT_BYTES_PER_PIXEL 4
34+
35+ // /////////////////////////////////////////////////////////////////////////////
36+ // Functions
37+ // /////////////////////////////////////////////////////////////////////////////
38+
39+ template <typename T>
40+ static inline T min (T a, T b) {
41+ return a < b ? a : b;
42+ }
43+
3144// /////////////////////////////////////////////////////////////////////////////
3245// Constructors/destructor
3346// /////////////////////////////////////////////////////////////////////////////
@@ -83,7 +96,7 @@ void GradientCache::setMaxSize(uint32_t maxSize) {
8396
8497void GradientCache::operator ()(GradientCacheEntry& shader, Texture*& texture) {
8598 if (texture) {
86- const uint32_t size = texture->width * texture->height * 4 ;
99+ const uint32_t size = texture->width * texture->height * GRADIENT_BYTES_PER_PIXEL ;
87100 mSize -= size;
88101 }
89102
@@ -97,14 +110,13 @@ void GradientCache::operator()(GradientCacheEntry& shader, Texture*& texture) {
97110// Caching
98111// /////////////////////////////////////////////////////////////////////////////
99112
100- Texture* GradientCache::get (uint32_t * colors, float * positions,
101- int count, SkShader::TileMode tileMode) {
113+ Texture* GradientCache::get (uint32_t * colors, float * positions, int count) {
102114
103- GradientCacheEntry gradient (colors, positions, count, tileMode );
115+ GradientCacheEntry gradient (colors, positions, count);
104116 Texture* texture = mCache .get (gradient);
105117
106118 if (!texture) {
107- texture = addLinearGradient (gradient, colors, positions, count, tileMode );
119+ texture = addLinearGradient (gradient, colors, positions, count);
108120 }
109121
110122 return texture;
@@ -114,65 +126,109 @@ void GradientCache::clear() {
114126 mCache .clear ();
115127}
116128
117- Texture* GradientCache::addLinearGradient (GradientCacheEntry& gradient,
118- uint32_t * colors, float * positions, int count, SkShader::TileMode tileMode) {
119- int width = 256 * (count - 1 );
120- width = width < mMaxTextureSize ? width : mMaxTextureSize ;
121-
122- SkBitmap bitmap;
123- bitmap.setConfig (SkBitmap::kARGB_8888_Config , width, 4 );
124- bitmap.allocPixels ();
125- bitmap.eraseColor (0 );
129+ void GradientCache::getGradientInfo (const uint32_t * colors, const int count,
130+ GradientInfo& info) {
131+ uint32_t width = 1 << (31 - __builtin_clz (256 * (count - 1 )));
132+ bool hasAlpha = false ;
126133
127- SkCanvas canvas (bitmap);
134+ for (int i = 0 ; i < count; i++) {
135+ if (((colors[i] >> 24 ) & 0xff ) < 255 ) {
136+ hasAlpha = true ;
137+ break ;
138+ }
139+ }
128140
129- SkPoint points[ 2 ] ;
130- points[ 0 ]. set ( 0 . 0f , 0 . 0f ) ;
131- points[ 1 ]. set (bitmap. width (), 0 . 0f );
141+ info. width = min (width, uint32_t ( mMaxTextureSize )) ;
142+ info. hasAlpha = hasAlpha ;
143+ }
132144
133- SkShader* localShader = SkGradientShader::CreateLinear (points ,
134- reinterpret_cast < const SkColor*>( colors), positions, count, tileMode);
145+ Texture* GradientCache::addLinearGradient (GradientCacheEntry& gradient ,
146+ uint32_t * colors, float * positions, int count) {
135147
136- SkPaint p;
137- p.setStyle (SkPaint::kStrokeAndFill_Style );
138- p.setShader (localShader)->unref ();
148+ GradientInfo info;
149+ getGradientInfo (colors, count, info);
139150
140- canvas.drawRectCoords (0 .0f , 0 .0f , bitmap.width (), 4 .0f , p);
151+ Texture* texture = new Texture;
152+ texture->width = info.width ;
153+ texture->height = GRADIENT_TEXTURE_HEIGHT;
154+ texture->blend = info.hasAlpha ;
155+ texture->generation = 1 ;
141156
142157 // Asume the cache is always big enough
143- const uint32_t size = bitmap. rowBytes () * bitmap. height () ;
158+ const uint32_t size = texture-> width * texture-> height * GRADIENT_BYTES_PER_PIXEL ;
144159 while (mSize + size > mMaxSize ) {
145160 mCache .removeOldest ();
146161 }
147162
148- Texture* texture = new Texture;
149- generateTexture (&bitmap, texture);
163+ generateTexture (colors, positions, count, texture);
150164
151165 mSize += size;
152166 mCache .put (gradient, texture);
153167
154168 return texture;
155169}
156170
157- void GradientCache::generateTexture (SkBitmap* bitmap, Texture* texture) {
158- SkAutoLockPixels autoLock (*bitmap);
159- if (!bitmap->readyToDraw ()) {
160- ALOGE (" Cannot generate texture from shader" );
161- return ;
171+ void GradientCache::generateTexture (uint32_t * colors, float * positions,
172+ int count, Texture* texture) {
173+
174+ const uint32_t width = texture->width ;
175+ const GLsizei rowBytes = width * GRADIENT_BYTES_PER_PIXEL;
176+ uint32_t pixels[width * texture->height ];
177+
178+ int currentPos = 1 ;
179+
180+ float startA = (colors[0 ] >> 24 ) & 0xff ;
181+ float startR = (colors[0 ] >> 16 ) & 0xff ;
182+ float startG = (colors[0 ] >> 8 ) & 0xff ;
183+ float startB = (colors[0 ] >> 0 ) & 0xff ;
184+
185+ float endA = (colors[1 ] >> 24 ) & 0xff ;
186+ float endR = (colors[1 ] >> 16 ) & 0xff ;
187+ float endG = (colors[1 ] >> 8 ) & 0xff ;
188+ float endB = (colors[1 ] >> 0 ) & 0xff ;
189+
190+ float start = positions[0 ];
191+ float distance = positions[1 ] - start;
192+
193+ uint8_t * p = (uint8_t *) pixels;
194+ for (uint32_t x = 0 ; x < width; x++) {
195+ float pos = x / float (width - 1 );
196+ if (pos > positions[currentPos]) {
197+ startA = endA;
198+ startR = endR;
199+ startG = endG;
200+ startB = endB;
201+ start = positions[currentPos];
202+
203+ currentPos++;
204+
205+ endA = (colors[currentPos] >> 24 ) & 0xff ;
206+ endR = (colors[currentPos] >> 16 ) & 0xff ;
207+ endG = (colors[currentPos] >> 8 ) & 0xff ;
208+ endB = (colors[currentPos] >> 0 ) & 0xff ;
209+ distance = positions[currentPos] - start;
210+ }
211+
212+ float amount = (pos - start) / distance;
213+ float oppAmount = 1 .0f - amount;
214+
215+ *p++ = uint8_t (startR * oppAmount + endR * amount);
216+ *p++ = uint8_t (startG * oppAmount + endG * amount);
217+ *p++ = uint8_t (startB * oppAmount + endB * amount);
218+ *p++ = uint8_t (startA * oppAmount + endA * amount);
162219 }
163220
164- texture-> generation = bitmap-> getGenerationID ();
165- texture-> width = bitmap-> width ( );
166- texture-> height = bitmap-> height ();
221+ for ( int i = 1 ; i < GRADIENT_TEXTURE_HEIGHT; i++) {
222+ memcpy (pixels + width * i, pixels, rowBytes );
223+ }
167224
168225 glGenTextures (1 , &texture->id );
169226
170227 glBindTexture (GL_TEXTURE_2D, texture->id );
171- glPixelStorei (GL_UNPACK_ALIGNMENT, bitmap-> bytesPerPixel () );
228+ glPixelStorei (GL_UNPACK_ALIGNMENT, GRADIENT_BYTES_PER_PIXEL );
172229
173- texture->blend = !bitmap->isOpaque ();
174- glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, bitmap->rowBytesAsPixels (), texture->height , 0 ,
175- GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels ());
230+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, width, texture->height , 0 ,
231+ GL_RGBA, GL_UNSIGNED_BYTE, pixels);
176232
177233 texture->setFilter (GL_LINEAR);
178234 texture->setWrap (GL_CLAMP_TO_EDGE);
0 commit comments