1 /* libs/pixelflinger/buffer.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 
19 #include <assert.h>
20 
21 #include <android-base/macros.h>
22 
23 #include "buffer.h"
24 
25 namespace android {
26 // ----------------------------------------------------------------------------
27 
28 static void read_pixel(const surface_t* s, context_t* c,
29         uint32_t x, uint32_t y, pixel_t* pixel);
30 static void write_pixel(const surface_t* s, context_t* c,
31         uint32_t x, uint32_t y, const pixel_t* pixel);
32 static void readRGB565(const surface_t* s, context_t* c,
33         uint32_t x, uint32_t y, pixel_t* pixel);
34 static void readABGR8888(const surface_t* s, context_t* c,
35         uint32_t x, uint32_t y, pixel_t* pixel);
36 
37 static uint32_t logic_op(int op, uint32_t s, uint32_t d);
38 static uint32_t extract(uint32_t v, int h, int l, int bits);
39 static uint32_t expand(uint32_t v, int sbits, int dbits);
40 static uint32_t downshift_component(uint32_t in, uint32_t v,
41         int sh, int sl, int dh, int dl, int ch, int cl, int dither);
42 
43 // ----------------------------------------------------------------------------
44 
ggl_init_texture(context_t * c)45 void ggl_init_texture(context_t* c)
46 {
47     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
48         texture_t& t = c->state.texture[i];
49         t.s_coord = GGL_ONE_TO_ONE;
50         t.t_coord = GGL_ONE_TO_ONE;
51         t.s_wrap = GGL_REPEAT;
52         t.t_wrap = GGL_REPEAT;
53         t.min_filter = GGL_NEAREST;
54         t.mag_filter = GGL_NEAREST;
55         t.env = GGL_MODULATE;
56     }
57     c->activeTMU = &(c->state.texture[0]);
58 }
59 
ggl_set_surface(context_t * c,surface_t * dst,const GGLSurface * src)60 void ggl_set_surface(context_t* c, surface_t* dst, const GGLSurface* src)
61 {
62     dst->width = src->width;
63     dst->height = src->height;
64     dst->stride = src->stride;
65     dst->data = src->data;
66     dst->format = src->format;
67     dst->dirty = 1;
68     if (__builtin_expect(dst->stride < 0, false)) {
69         const GGLFormat& pixelFormat(c->formats[dst->format]);
70         const int32_t bpr = -dst->stride * pixelFormat.size;
71         dst->data += bpr * (dst->height-1);
72     }
73 }
74 
pick_read_write(surface_t * s)75 static void pick_read_write(surface_t* s)
76 {
77     // Choose best reader/writers.
78     switch (s->format) {
79         case GGL_PIXEL_FORMAT_RGBA_8888:    s->read = readABGR8888;  break;
80         case GGL_PIXEL_FORMAT_RGB_565:      s->read = readRGB565;    break;
81         default:                            s->read = read_pixel;    break;
82     }
83     s->write = write_pixel;
84 }
85 
ggl_pick_texture(context_t * c)86 void ggl_pick_texture(context_t* c)
87 {
88     for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; ++i) {
89         surface_t& s = c->state.texture[i].surface;
90         if ((!c->state.texture[i].enable) || (!s.dirty))
91             continue;
92         s.dirty = 0;
93         pick_read_write(&s);
94         generated_tex_vars_t& gen = c->generated_vars.texture[i];
95         gen.width   = s.width;
96         gen.height  = s.height;
97         gen.stride  = s.stride;
98         gen.data    = uintptr_t(s.data);
99     }
100 }
101 
ggl_pick_cb(context_t * c)102 void ggl_pick_cb(context_t* c)
103 {
104     surface_t& s = c->state.buffers.color;
105     if (s.dirty) {
106         s.dirty = 0;
107         pick_read_write(&s);
108     }
109 }
110 
111 // ----------------------------------------------------------------------------
112 
read_pixel(const surface_t * s,context_t * c,uint32_t x,uint32_t y,pixel_t * pixel)113 void read_pixel(const surface_t* s, context_t* c,
114         uint32_t x, uint32_t y, pixel_t* pixel)
115 {
116     assert((x < s->width) && (y < s->height));
117 
118     const GGLFormat* f = &(c->formats[s->format]);
119     int32_t index = x + (s->stride * y);
120     uint8_t* const data = s->data + index * f->size;
121     uint32_t v = 0;
122     switch (f->size) {
123         case 1:		v = *data;									break;
124         case 2:		v = *(uint16_t*)data;						break;
125         case 3:		v = (data[2]<<16)|(data[1]<<8)|data[0];     break;
126         case 4:		v = GGL_RGBA_TO_HOST(*(uint32_t*)data);		break;
127     }
128     for (int i=0 ; i<4 ; i++) {
129         pixel->s[i] = f->c[i].h - f->c[i].l;
130         if (pixel->s[i])
131             pixel->c[i] = extract(v,  f->c[i].h,  f->c[i].l, f->size*8);
132     }
133 }
134 
readRGB565(const surface_t * s,context_t *,uint32_t x,uint32_t y,pixel_t * pixel)135 void readRGB565(const surface_t* s, context_t* /*c*/,
136         uint32_t x, uint32_t y, pixel_t* pixel)
137 {
138     uint16_t v = *(reinterpret_cast<uint16_t*>(s->data) + (x + (s->stride * y)));
139     pixel->c[0] = 0;
140     pixel->c[1] = v>>11;
141     pixel->c[2] = (v>>5)&0x3F;
142     pixel->c[3] = v&0x1F;
143     pixel->s[0] = 0;
144     pixel->s[1] = 5;
145     pixel->s[2] = 6;
146     pixel->s[3] = 5;
147 }
148 
readABGR8888(const surface_t * s,context_t *,uint32_t x,uint32_t y,pixel_t * pixel)149 void readABGR8888(const surface_t* s, context_t* /*c*/,
150         uint32_t x, uint32_t y, pixel_t* pixel)
151 {
152     uint32_t v = *(reinterpret_cast<uint32_t*>(s->data) + (x + (s->stride * y)));
153     v = GGL_RGBA_TO_HOST(v);
154     pixel->c[0] = v>>24;        // A
155     pixel->c[1] = v&0xFF;       // R
156     pixel->c[2] = (v>>8)&0xFF;  // G
157     pixel->c[3] = (v>>16)&0xFF; // B
158     pixel->s[0] =
159     pixel->s[1] =
160     pixel->s[2] =
161     pixel->s[3] = 8;
162 }
163 
write_pixel(const surface_t * s,context_t * c,uint32_t x,uint32_t y,const pixel_t * pixel)164 void write_pixel(const surface_t* s, context_t* c,
165         uint32_t x, uint32_t y, const pixel_t* pixel)
166 {
167     assert((x < s->width) && (y < s->height));
168 
169     int dither = -1;
170     if (c->state.enables & GGL_ENABLE_DITHER) {
171         dither = c->ditherMatrix[ (x & GGL_DITHER_MASK) +
172                 ((y & GGL_DITHER_MASK)<<GGL_DITHER_ORDER_SHIFT) ];
173     }
174 
175     const GGLFormat* f = &(c->formats[s->format]);
176     int32_t index = x + (s->stride * y);
177     uint8_t* const data = s->data + index * f->size;
178 
179     uint32_t mask = 0;
180     uint32_t v = 0;
181     for (int i=0 ; i<4 ; i++) {
182         const int component_mask = 1 << i;
183         if (f->components>=GGL_LUMINANCE &&
184                 (i==GGLFormat::GREEN || i==GGLFormat::BLUE)) {
185             // destinations L formats don't have G or B
186             continue;
187         }
188         const int l = f->c[i].l;
189         const int h = f->c[i].h;
190         if (h && (c->state.mask.color & component_mask)) {
191             mask |= (((1<<(h-l))-1)<<l);
192             uint32_t u = pixel->c[i];
193             int32_t pixelSize = pixel->s[i];
194             if (pixelSize < (h-l)) {
195                 u = expand(u, pixelSize, h-l);
196                 pixelSize = h-l;
197             }
198             v = downshift_component(v, u, pixelSize, 0, h, l, 0, 0, dither);
199         }
200     }
201 
202     if ((c->state.mask.color != 0xF) ||
203         (c->state.enables & GGL_ENABLE_LOGIC_OP)) {
204         uint32_t d = 0;
205         switch (f->size) {
206             case 1:	d = *data;									break;
207             case 2:	d = *(uint16_t*)data;						break;
208             case 3:	d = (data[2]<<16)|(data[1]<<8)|data[0];     break;
209             case 4:	d = GGL_RGBA_TO_HOST(*(uint32_t*)data);		break;
210         }
211         if (c->state.enables & GGL_ENABLE_LOGIC_OP) {
212             v = logic_op(c->state.logic_op.opcode, v, d);
213             v &= mask;
214         }
215         v |= (d & ~mask);
216     }
217 
218     switch (f->size) {
219         case 1:		*data = v;									break;
220         case 2:		*(uint16_t*)data = v;						break;
221         case 3:
222             data[0] = v;
223             data[1] = v>>8;
224             data[2] = v>>16;
225             break;
226         case 4:		*(uint32_t*)data = GGL_HOST_TO_RGBA(v);     break;
227     }
228 }
229 
logic_op(int op,uint32_t s,uint32_t d)230 static uint32_t logic_op(int op, uint32_t s, uint32_t d)
231 {
232     switch(op) {
233     case GGL_CLEAR:         return 0;
234     case GGL_AND:           return s & d;
235     case GGL_AND_REVERSE:   return s & ~d;
236     case GGL_COPY:          return s;
237     case GGL_AND_INVERTED:  return ~s & d;
238     case GGL_NOOP:          return d;
239     case GGL_XOR:           return s ^ d;
240     case GGL_OR:            return s | d;
241     case GGL_NOR:           return ~(s | d);
242     case GGL_EQUIV:         return ~(s ^ d);
243     case GGL_INVERT:        return ~d;
244     case GGL_OR_REVERSE:    return s | ~d;
245     case GGL_COPY_INVERTED: return ~s;
246     case GGL_OR_INVERTED:   return ~s | d;
247     case GGL_NAND:          return ~(s & d);
248     case GGL_SET:           return ~0;
249     };
250     return s;
251 }
252 
253 
ggl_expand(uint32_t v,int sbits,int dbits)254 uint32_t ggl_expand(uint32_t v, int sbits, int dbits)
255 {
256     return expand(v, sbits, dbits);
257 }
258 
ggl_pack_color(context_t * c,int32_t format,GGLcolor r,GGLcolor g,GGLcolor b,GGLcolor a)259 uint32_t ggl_pack_color(context_t* c, int32_t format,
260         GGLcolor r, GGLcolor g, GGLcolor b, GGLcolor a)
261 {
262     const GGLFormat* f = &(c->formats[format]);
263     uint32_t p = 0;
264     const int32_t hbits = GGL_COLOR_BITS;
265     const int32_t lbits = GGL_COLOR_BITS - 8;
266     p = downshift_component(p, r,   hbits, lbits,  f->rh, f->rl, 0, 1, -1);
267     p = downshift_component(p, g,   hbits, lbits,  f->gh, f->gl, 0, 1, -1);
268     p = downshift_component(p, b,   hbits, lbits,  f->bh, f->bl, 0, 1, -1);
269     p = downshift_component(p, a,   hbits, lbits,  f->ah, f->al, 0, 1, -1);
270     switch (f->size) {
271         case 1:
272             p |= p << 8;
273             FALLTHROUGH_INTENDED;
274         case 2:
275             p |= p << 16;
276     }
277     return p;
278 }
279 
280 // ----------------------------------------------------------------------------
281 
282 // extract a component from a word
extract(uint32_t v,int h,int l,int bits)283 uint32_t extract(uint32_t v, int h, int l, int bits)
284 {
285 	assert(h);
286 	if (l) {
287 		v >>= l;
288 	}
289 	if (h != bits) {
290 		v &= (1<<(h-l))-1;
291 	}
292 	return v;
293 }
294 
295 // expand a component from sbits to dbits
expand(uint32_t v,int sbits,int dbits)296 uint32_t expand(uint32_t v, int sbits, int dbits)
297 {
298     if (dbits > sbits) {
299         assert(sbits);
300         if (sbits==1) {
301             v = (v<<dbits) - v;
302         } else {
303             if (dbits % sbits) {
304                 v <<= (dbits-sbits);
305                 dbits -= sbits;
306                 do {
307                     v |= v>>sbits;
308                     dbits -= sbits;
309                     sbits *= 2;
310                 } while (dbits>0);
311             } else {
312                 dbits -= sbits;
313                 do {
314                     v |= v<<sbits;
315                     dbits -= sbits;
316                     if (sbits*2 < dbits) {
317                         sbits *= 2;
318                     }
319                 } while (dbits > 0);
320             }
321         }
322     }
323 	return v;
324 }
325 
326 // downsample a component from sbits to dbits
327 // and shift / construct the pixel
downshift_component(uint32_t in,uint32_t v,int sh,int sl,int dh,int dl,int ch,int cl,int dither)328 uint32_t downshift_component(	uint32_t in, uint32_t v,
329                                 int sh, int sl,		// src
330                                 int dh, int dl,		// dst
331                                 int ch, int cl,		// clear
332                                 int dither)
333 {
334 	const int sbits = sh-sl;
335 	const int dbits = dh-dl;
336 
337 	assert(sbits>=dbits);
338 
339 
340     if (sbits>dbits) {
341         if (dither>=0) {
342             v -= (v>>dbits);				// fix up
343             const int shift = (GGL_DITHER_BITS - (sbits-dbits));
344             if (shift >= 0)   v += (dither >> shift) << sl;
345             else              v += (dither << (-shift)) << sl;
346         } else {
347             // don't do that right now, so we can reproduce the same
348             // artifacts we get on ARM (Where we don't do this)
349             // -> this is not really needed if we don't dither
350             //if (dBits > 1) { // result already OK if dBits==1
351             //    v -= (v>>dbits);				// fix up
352             //    v += 1 << ((sbits-dbits)-1);	// rounding
353             //}
354         }
355     }
356 
357 
358 	// we need to clear the high bits of the source
359 	if (ch) {
360 		v <<= 32-sh;
361 		sl += 32-sh;
362         sh = 32;
363 	}
364 
365 	if (dl) {
366 		if (cl || (sbits>dbits)) {
367 			v >>= sh-dbits;
368 			sl = 0;
369 			sh = dbits;
370             in |= v<<dl;
371 		} else {
372 			// sbits==dbits and we don't need to clean the lower bits
373 			// so we just have to shift the component to the right location
374             int shift = dh-sh;
375             in |= v<<shift;
376 		}
377 	} else {
378 		// destination starts at bit 0
379 		// ie: sh-dh == sh-dbits
380 		int shift = sh-dh;
381 		if (shift > 0)      in |= v>>shift;
382 		else if (shift < 0) in |= v<<shift;
383 		else                in |= v;
384 	}
385 	return in;
386 }
387 
388 // ----------------------------------------------------------------------------
389 }; // namespace android
390