Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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