blob: 73b2355aa8ecbce1c514ae0b29dc39a0042f9299 [file] [log] [blame]
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001/*
2**
3** Copyright 2009, 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#include <stdlib.h>
19#include <stdio.h>
20
21#include "context.h"
22#include "fp.h"
23#include "state.h"
24#include "matrix.h"
25#include "vertex.h"
26#include "light.h"
27#include "primitives.h"
28#include "texture.h"
29#include "BufferObjectManager.h"
Mathias Agopian076b1cc2009-04-10 14:24:30 -070030#include "TextureObjectManager.h"
Mathias Agopian0a3139a2009-06-10 16:01:54 -070031
Mathias Agopian076b1cc2009-04-10 14:24:30 -070032#include <hardware/gralloc.h>
33#include <hardware/copybit.h>
Mathias Agopian0a3139a2009-06-10 16:01:54 -070034#include <private/ui/android_natives_priv.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070035
Mathias Agopian6d2cad22009-06-17 21:18:56 -070036
37#define DEBUG_COPYBIT true
38
Mathias Agopian076b1cc2009-04-10 14:24:30 -070039// ----------------------------------------------------------------------------
40
41namespace android {
42
Mathias Agopian0a3139a2009-06-10 16:01:54 -070043static void textureToCopyBitImage(
Mathias Agopian6dbedd72009-10-16 16:17:58 -070044 const GGLSurface* surface, int32_t opFormat,
45 buffer_handle_t buffer, copybit_image_t* img)
Mathias Agopian0a3139a2009-06-10 16:01:54 -070046{
Mathias Agopian076b1cc2009-04-10 14:24:30 -070047 img->w = surface->stride;
48 img->h = surface->height;
Mathias Agopian6dbedd72009-10-16 16:17:58 -070049 img->format = opFormat;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070050 img->base = surface->data;
Mathias Agopian5911aa92009-06-24 16:55:59 -070051 img->handle = (native_handle_t *)buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070052}
53
54struct clipRectRegion : public copybit_region_t {
Mathias Agopiancf251b92009-06-16 18:08:29 -070055 clipRectRegion(ogles_context_t* c)
56 {
57 scissor_t const* scissor = &c->rasterizer.state.scissor;
58 r.l = scissor->left;
59 r.t = scissor->top;
60 r.r = scissor->right;
61 r.b = scissor->bottom;
62 next = iterate;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070063 }
64private:
65 static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
Mathias Agopiancf251b92009-06-16 18:08:29 -070066 *rect = static_cast<clipRectRegion const*>(self)->r;
67 const_cast<copybit_region_t *>(self)->next = iterate_done;
68 return 1;
69 }
70 static int iterate_done(copybit_region_t const *, copybit_rect_t*) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -070071 return 0;
72 }
Mathias Agopiancf251b92009-06-16 18:08:29 -070073 copybit_rect_t r;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070074};
75
76static bool supportedCopybitsFormat(int format) {
77 switch (format) {
78 case COPYBIT_FORMAT_RGBA_8888:
Mathias Agopiandfbec0e2009-08-07 20:55:14 -070079 case COPYBIT_FORMAT_RGBX_8888:
80 case COPYBIT_FORMAT_RGB_888:
Mathias Agopian076b1cc2009-04-10 14:24:30 -070081 case COPYBIT_FORMAT_RGB_565:
82 case COPYBIT_FORMAT_BGRA_8888:
83 case COPYBIT_FORMAT_RGBA_5551:
84 case COPYBIT_FORMAT_RGBA_4444:
85 case COPYBIT_FORMAT_YCbCr_422_SP:
86 case COPYBIT_FORMAT_YCbCr_420_SP:
87 return true;
88 default:
89 return false;
90 }
91}
92
93static bool hasAlpha(int format) {
94 switch (format) {
95 case COPYBIT_FORMAT_RGBA_8888:
96 case COPYBIT_FORMAT_BGRA_8888:
97 case COPYBIT_FORMAT_RGBA_5551:
98 case COPYBIT_FORMAT_RGBA_4444:
99 return true;
100 default:
101 return false;
102 }
103}
104
105static inline int fixedToByte(GGLfixed val) {
106 return (val - (val >> 8)) >> 8;
107}
108
109/**
110 * Performs a quick check of the rendering state. If this function returns
111 * false we cannot use the copybit driver.
112 */
113
114static bool checkContext(ogles_context_t* c) {
115
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700116 // By convention copybitQuickCheckContext() has already returned true.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700117 // avoid checking the same information again.
118
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700119 if (c->copybits.blitEngine == NULL) {
120 LOGD_IF(DEBUG_COPYBIT, "no copybit hal");
121 return false;
122 }
123
124 if (c->rasterizer.state.enables
125 & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) {
126 LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700127 return false;
128 }
129
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700130 // Note: The drawSurfaceBuffer is only set for destination
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700131 // surfaces types that are supported by the hardware and
132 // do not have an alpha channel. So we don't have to re-check that here.
133
134 static const int tmu = 0;
135 texture_unit_t& u(c->textures.tmu[tmu]);
136 EGLTextureObject* textureObject = u.texture;
137
138 if (!supportedCopybitsFormat(textureObject->surface.format)) {
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700139 LOGD_IF(DEBUG_COPYBIT, "texture format not supported");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700140 return false;
141 }
142 return true;
143}
144
145
146static bool copybit(GLint x, GLint y,
147 GLint w, GLint h,
148 EGLTextureObject* textureObject,
149 const GLint* crop_rect,
150 int transform,
151 ogles_context_t* c)
152{
153 // We assume checkContext has already been called and has already
154 // returned true.
155
156 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
157
158 y = cbSurface.height - (y + h);
159
160 const GLint Ucr = crop_rect[0];
161 const GLint Vcr = crop_rect[1];
162 const GLint Wcr = crop_rect[2];
163 const GLint Hcr = crop_rect[3];
164
Mathias Agopian295eff22009-06-29 16:36:49 -0700165 GLint screen_w = w;
166 GLint screen_h = h;
167 int32_t dsdx = Wcr << 16; // dsdx = ((Wcr/screen_w)/Wt)*Wt
168 int32_t dtdy = Hcr << 16; // dtdy = -((Hcr/screen_h)/Ht)*Ht
Mathias Agopiane7829b82009-06-23 18:31:06 -0700169 if (transform & COPYBIT_TRANSFORM_ROT_90) {
Mathias Agopian295eff22009-06-29 16:36:49 -0700170 swap(screen_w, screen_h);
Mathias Agopiane7829b82009-06-23 18:31:06 -0700171 }
Mathias Agopian295eff22009-06-29 16:36:49 -0700172 if (dsdx!=screen_w || dtdy!=screen_h) {
173 // in most cases the divide is not needed
174 dsdx /= screen_w;
175 dtdy /= screen_h;
176 }
177 dtdy = -dtdy; // see equation of dtdy above
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700178 if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
179 || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
180 // The requested scale is out of the range the hardware
181 // can support.
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700182 LOGD_IF(DEBUG_COPYBIT,
Mathias Agopiane7829b82009-06-23 18:31:06 -0700183 "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
184 "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
185 dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700186 return false;
187 }
188
Mathias Agopianaa6e88b2009-06-17 21:58:18 -0700189 // copybit doesn't say anything about filtering, so we can't
190 // discriminate. On msm7k, copybit will always filter.
191 // the code below handles min/mag filters, we keep it as a reference.
192
193#ifdef MIN_MAG_FILTER
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700194 int32_t texelArea = gglMulx(dtdy, dsdx);
195 if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) {
196 // Non-linear filtering on a texture enlargement.
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700197 LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700198 return false;
199 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700200 if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) {
201 // Non-linear filtering on an texture shrink.
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700202 LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700203 return false;
204 }
Mathias Agopianaa6e88b2009-06-17 21:58:18 -0700205#endif
206
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700207 const uint32_t enables = c->rasterizer.state.enables;
208 int planeAlpha = 255;
209 static const int tmu = 0;
210 texture_t& tev(c->rasterizer.state.texture[tmu]);
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700211 int32_t opFormat = textureObject->surface.format;
212 const bool srcTextureHasAlpha = hasAlpha(opFormat);
Mathias Agopiane7829b82009-06-23 18:31:06 -0700213 if (!srcTextureHasAlpha) {
214 planeAlpha = fixedToByte(c->currentColorClamped.a);
215 }
216
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700217 const bool cbHasAlpha = hasAlpha(cbSurface.format);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700218 bool blending = false;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700219 if ((enables & GGL_ENABLE_BLENDING)
220 && !(c->rasterizer.state.blend.src == GL_ONE
221 && c->rasterizer.state.blend.dst == GL_ZERO)) {
222 // Blending is OK if it is
223 // the exact kind of blending that the copybits hardware supports.
224 // Note: The hardware only supports
225 // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA,
226 // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA.
227 // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case,
228 // because the performance is worth it, even if the results are
229 // not correct.
230 if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA
231 || c->rasterizer.state.blend.src == GL_ONE)
232 && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA
233 && c->rasterizer.state.blend.alpha_separate == 0)) {
234 // Incompatible blend mode.
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700235 LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700236 return false;
237 }
238 blending = true;
239 } else {
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700240 if (cbHasAlpha) {
241 // NOTE: the result will be slightly wrong in this case because
242 // the destination alpha channel will be set to 1.0 instead of
243 // the iterated alpha value. *shrug*.
244 }
245 // disable plane blending and src blending for supported formats
246 planeAlpha = 255;
247 if (opFormat == COPYBIT_FORMAT_RGBA_8888) {
248 opFormat = COPYBIT_FORMAT_RGBX_8888;
249 } else {
250 if (srcTextureHasAlpha) {
251 LOGD_IF(DEBUG_COPYBIT, "texture format requires blending");
252 return false;
253 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700254 }
255 }
256
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700257 switch (tev.env) {
258 case GGL_REPLACE:
259 break;
260 case GGL_MODULATE:
261 // only cases allowed is:
262 // RGB source, color={1,1,1,a} -> can be done with GL_REPLACE
263 // RGBA source, color={1,1,1,1} -> can be done with GL_REPLACE
264 if (blending) {
265 if (c->currentColorClamped.r == c->currentColorClamped.a &&
266 c->currentColorClamped.g == c->currentColorClamped.a &&
267 c->currentColorClamped.b == c->currentColorClamped.a) {
268 // TODO: Need to emulate: RGBA source, color={a,a,a,a} / premult
269 // and RGBA source, color={1,1,1,a} / regular-blending
270 // (both are equivalent)
271 }
272 }
273 LOGD_IF(DEBUG_COPYBIT, "GGL_MODULATE");
274 return false;
275 default:
276 // Incompatible texture environment.
277 LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700278 return false;
279 }
280
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700281
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700282 // LOGW("calling copybits");
283
284 copybit_device_t* copybit = c->copybits.blitEngine;
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700285
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700286 copybit_image_t dst;
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700287 buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer;
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700288 textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700289 copybit_rect_t drect = {x, y, x+w, y+h};
290
291 copybit_image_t src;
Mathias Agopian0a3139a2009-06-10 16:01:54 -0700292 buffer_handle_t source_hnd = textureObject->buffer->handle;
Mathias Agopian6dbedd72009-10-16 16:17:58 -0700293 textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700294 copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
295
296 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
297 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700298 copybit->set_parameter(copybit, COPYBIT_DITHER,
299 (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE);
300
301 clipRectRegion it(c);
Mathias Agopian295eff22009-06-29 16:36:49 -0700302 status_t err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
Mathias Agopianf13901e2009-07-15 18:53:32 -0700303 if (err != NO_ERROR) {
304 c->textures.tmu[0].texture->try_copybit = false;
305 }
Mathias Agopian295eff22009-06-29 16:36:49 -0700306 return err == NO_ERROR ? true : false;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700307}
308
309/*
310 * Try to draw a triangle fan with copybit, return false if we fail.
311 */
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700312bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count)
313{
314 if (!checkContext(c)) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700315 return false;
316 }
317
Mathias Agopian7272add2009-06-18 19:31:07 -0700318 // FIXME: we should handle culling here
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700319 c->arrays.compileElements(c, c->vc.vBuffer, 0, 4);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700320
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700321 // we detect if we're dealing with a rectangle, by comparing the
322 // rectangles {v0,v2} and {v1,v3} which should be identical.
323
Mathias Agopianaa6e88b2009-06-17 21:58:18 -0700324 // NOTE: we should check that the rectangle is window aligned, however
325 // if we do that, the optimization won't be taken in a lot of cases.
326 // Since this code is intended to be used with SurfaceFlinger only,
327 // so it's okay...
328
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700329 const vec4_t& v0 = c->vc.vBuffer[0].window;
330 const vec4_t& v1 = c->vc.vBuffer[1].window;
331 const vec4_t& v2 = c->vc.vBuffer[2].window;
332 const vec4_t& v3 = c->vc.vBuffer[3].window;
333 int l = min(v0.x, v2.x);
334 int b = min(v0.y, v2.y);
335 int r = max(v0.x, v2.x);
336 int t = max(v0.y, v2.y);
337 if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) ||
338 (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) {
339 LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle");
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700340 return false;
341 }
Mathias Agopian7272add2009-06-18 19:31:07 -0700342
343 // fetch and transform texture coordinates
344 // NOTE: maybe it would be better to have a "compileElementsAll" method
345 // that would ensure all vertex data are fetched and transformed
346 const transform_t& tr = c->transforms.texture[0].transform;
347 for (size_t i=0 ; i<4 ; i++) {
348 const GLubyte* tp = c->arrays.texture[0].element(i);
349 vertex_t* const v = &c->vc.vBuffer[i];
350 c->arrays.texture[0].fetch(c, v->texture[0].v, tp);
351 // FIXME: we should bail if q!=1
352 c->arrays.tex_transform[0](&tr, &v->texture[0], &v->texture[0]);
353 }
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700354
355 const vec4_t& t0 = c->vc.vBuffer[0].texture[0];
356 const vec4_t& t1 = c->vc.vBuffer[1].texture[0];
357 const vec4_t& t2 = c->vc.vBuffer[2].texture[0];
358 const vec4_t& t3 = c->vc.vBuffer[3].texture[0];
359 int txl = min(t0.x, t2.x);
360 int txb = min(t0.y, t2.y);
361 int txr = max(t0.x, t2.x);
362 int txt = max(t0.y, t2.y);
363 if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) ||
364 (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) {
365 LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle");
366 return false;
367 }
368 if ((txl != 0) || (txb != 0) ||
369 (txr != FIXED_ONE) || (txt != FIXED_ONE)) {
370 // we could probably handle this case, if we wanted to
Mathias Agopian7272add2009-06-18 19:31:07 -0700371 LOGD_IF(DEBUG_COPYBIT, "texture is cropped: %08x,%08x,%08x,%08x",
372 txl, txb, txr, txt);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700373 return false;
374 }
375
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700376 // at this point, we know we are dealing with a rectangle, so we
377 // only need to consider 3 vertices for computing the jacobians
378
379 const int dx01 = v1.x - v0.x;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700380 const int dx02 = v2.x - v0.x;
Mathias Agopian295eff22009-06-29 16:36:49 -0700381 const int dy01 = v1.y - v0.y;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700382 const int dy02 = v2.y - v0.y;
383 const int ds01 = t1.S - t0.S;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700384 const int ds02 = t2.S - t0.S;
Mathias Agopian295eff22009-06-29 16:36:49 -0700385 const int dt01 = t1.T - t0.T;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700386 const int dt02 = t2.T - t0.T;
387 const int area = dx01*dy02 - dy01*dx02;
388 int dsdx, dsdy, dtdx, dtdy;
389 if (area >= 0) {
390 dsdx = ds01*dy02 - ds02*dy01;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700391 dtdx = dt01*dy02 - dt02*dy01;
Mathias Agopian295eff22009-06-29 16:36:49 -0700392 dsdy = ds02*dx01 - ds01*dx02;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700393 dtdy = dt02*dx01 - dt01*dx02;
394 } else {
395 dsdx = ds02*dy01 - ds01*dy02;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700396 dtdx = dt02*dy01 - dt01*dy02;
Mathias Agopian295eff22009-06-29 16:36:49 -0700397 dsdy = ds01*dx02 - ds02*dx01;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700398 dtdy = dt01*dx02 - dt02*dx01;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700399 }
400
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700401 // here we rely on the fact that we know the transform is
402 // a rigid-body transform AND that it can only rotate in 90 degrees
403 // increments
404
405 int transform = 0;
406 if (dsdx == 0) {
407 // 90 deg rotation case
408 // [ 0 dtdx ]
409 // [ dsdx 0 ]
410 transform |= COPYBIT_TRANSFORM_ROT_90;
411 // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted
412 if (dtdx > 0)
413 transform |= COPYBIT_TRANSFORM_FLIP_H;
414 if (dsdy < 0)
415 transform |= COPYBIT_TRANSFORM_FLIP_V;
416 } else {
417 // [ dsdx 0 ]
418 // [ 0 dtdy ]
419 if (dsdx < 0)
420 transform |= COPYBIT_TRANSFORM_FLIP_H;
421 if (dtdy < 0)
422 transform |= COPYBIT_TRANSFORM_FLIP_V;
423 }
424
425 //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform);
426 //LOGD("A=%f\tB=%f\nC=%f\tD=%f",
427 // dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0);
428
429 int x = l >> 4;
430 int y = b >> 4;
431 int w = (r-l) >> 4;
432 int h = (t-b) >> 4;
433 texture_unit_t& u(c->textures.tmu[0]);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700434 EGLTextureObject* textureObject = u.texture;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700435 GLint tWidth = textureObject->surface.width;
436 GLint tHeight = textureObject->surface.height;
437 GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight};
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700438 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s;
439 y = cbSurface.height - (y + h);
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700440 return copybit(x, y, w, h, textureObject, crop_rect, transform, c);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700441}
442
443/*
444 * Try to drawTexiOESWithCopybit, return false if we fail.
445 */
446
447bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z,
448 GLint w, GLint h, ogles_context_t* c)
449{
450 // quickly process empty rects
451 if ((w|h) <= 0) {
452 return true;
453 }
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700454 if (!checkContext(c)) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700455 return false;
456 }
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700457 texture_unit_t& u(c->textures.tmu[0]);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700458 EGLTextureObject* textureObject = u.texture;
Mathias Agopian6d2cad22009-06-17 21:18:56 -0700459 return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700460}
461
462} // namespace android
463