diff options
author | 2009-06-17 21:18:56 -0700 | |
---|---|---|
committer | 2009-06-17 21:18:56 -0700 | |
commit | 03a1b0116b115c214c16fa1a02a46999312fd0f2 (patch) | |
tree | eeceaccdf88d14dce6be2150ccd0cdb8d8d9849d | |
parent | 4d63fb113b542f0474c16d8f2c8a1240b44f0ca2 (diff) |
s/w OpenGL no detects and handles all any combinations of triangle fans corresponding to a rectangle
this allows fallback to faster copybit code in almost all cases.
-rw-r--r-- | opengl/libagl/array.cpp | 2 | ||||
-rw-r--r-- | opengl/libagl/copybit.cpp | 187 | ||||
-rw-r--r-- | opengl/libagl/copybit.h | 10 |
3 files changed, 122 insertions, 77 deletions
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index cffe880edd0d..f414ee5f7c3a 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -708,7 +708,7 @@ void drawPrimitivesTriangleStrip(ogles_context_t* c, void drawPrimitivesTriangleFan(ogles_context_t* c, GLint first, GLsizei count) { #ifdef LIBAGL_USE_GRALLOC_COPYBITS - if (drawTrangleFanWithCopybit(c, first, count)) { + if (drawTriangleFanWithCopybit(c, first, count)) { return; } #endif // LIBAGL_USE_GRALLOC_COPYBITS diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index d57a6e429081..0736b6b7b374 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -34,6 +34,9 @@ #include <private/ui/android_natives_priv.h> #include "gralloc_priv.h" + +#define DEBUG_COPYBIT true + // ---------------------------------------------------------------------------- namespace android { @@ -114,9 +117,14 @@ static bool checkContext(ogles_context_t* c) { // By convention copybitQuickCheckContext() has already returned true. // avoid checking the same information again. - if (c->copybits.blitEngine == NULL - || (c->rasterizer.state.enables - & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) { + if (c->copybits.blitEngine == NULL) { + LOGD_IF(DEBUG_COPYBIT, "no copybit hal"); + return false; + } + + if (c->rasterizer.state.enables + & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) { + LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog"); return false; } @@ -129,6 +137,7 @@ static bool checkContext(ogles_context_t* c) { EGLTextureObject* textureObject = u.texture; if (!supportedCopybitsFormat(textureObject->surface.format)) { + LOGD_IF(DEBUG_COPYBIT, "texture format not supported"); return false; } return true; @@ -161,19 +170,25 @@ static bool copybit(GLint x, GLint y, || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { // The requested scale is out of the range the hardware // can support. + LOGD_IF(DEBUG_COPYBIT, + "scale out of range dsdx=%08x, dtdy=%08x", dsdx, dtdy); return false; } + /* int32_t texelArea = gglMulx(dtdy, dsdx); if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) { // Non-linear filtering on a texture enlargement. + LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR"); return false; } if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) { // Non-linear filtering on an texture shrink. + LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR"); return false; } + */ const uint32_t enables = c->rasterizer.state.enables; int planeAlpha = 255; @@ -192,6 +207,7 @@ static bool copybit(GLint x, GLint y, if (! (c->currentColorClamped.r == FIXED_ONE && c->currentColorClamped.g == FIXED_ONE && c->currentColorClamped.b == FIXED_ONE)) { + LOGD_IF(DEBUG_COPYBIT, "MODULATE and non white color"); return false; } planeAlpha = fixedToByte(c->currentColorClamped.a); @@ -199,6 +215,7 @@ static bool copybit(GLint x, GLint y, default: // Incompatible texture environment. + LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment"); return false; } @@ -220,6 +237,7 @@ static bool copybit(GLint x, GLint y, && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA && c->rasterizer.state.blend.alpha_separate == 0)) { // Incompatible blend mode. + LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode"); return false; } blending = true; @@ -227,12 +245,14 @@ static bool copybit(GLint x, GLint y, // No blending is OK if we are not using alpha. if (srcTextureHasAlpha || planeAlpha != 255) { // Incompatible alpha + LOGD_IF(DEBUG_COPYBIT, "incompatible alpha"); return false; } } if (srcTextureHasAlpha && planeAlpha != 255) { // Can't do two types of alpha at once. + LOGD_IF(DEBUG_COPYBIT, "src alpha and plane alpha"); return false; } @@ -264,86 +284,116 @@ static bool copybit(GLint x, GLint y, /* * Try to draw a triangle fan with copybit, return false if we fail. */ -bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) { - if (! checkContext(c)) { +bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) +{ + if (!checkContext(c)) { return false; } c->arrays.compileElements(c, c->vc.vBuffer, 0, 4); - // Is the result a screen aligned rectangle? - int sx[4]; - int sy[4]; - for (int i = 0; i < 4; i++) { - GLfixed x = c->vc.vBuffer[i].window.x; - GLfixed y = c->vc.vBuffer[i].window.y; - if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) { - return false; - } - sx[i] = x >> 4; - sy[i] = y >> 4; - } - /* - * This is the pattern we're looking for: - * (2)--(3) - * |\ | - * | \ | - * | \ | - * | \| - * (1)--(0) - * - */ - int dx[4]; - int dy[4]; - for (int i = 0; i < 4; i++) { - int i1 = (i + 1) & 3; - dx[i] = sx[i] - sx[i1]; - dy[i] = sy[i] - sy[i1]; + // we detect if we're dealing with a rectangle, by comparing the + // rectangles {v0,v2} and {v1,v3} which should be identical. + + const vec4_t& v0 = c->vc.vBuffer[0].window; + const vec4_t& v1 = c->vc.vBuffer[1].window; + const vec4_t& v2 = c->vc.vBuffer[2].window; + const vec4_t& v3 = c->vc.vBuffer[3].window; + int l = min(v0.x, v2.x); + int b = min(v0.y, v2.y); + int r = max(v0.x, v2.x); + int t = max(v0.y, v2.y); + if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) || + (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) { + LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle"); + return false; } - if (dx[1] | dx[3] | dy[0] | dy[2]) { + + const vec4_t& t0 = c->vc.vBuffer[0].texture[0]; + const vec4_t& t1 = c->vc.vBuffer[1].texture[0]; + const vec4_t& t2 = c->vc.vBuffer[2].texture[0]; + const vec4_t& t3 = c->vc.vBuffer[3].texture[0]; + int txl = min(t0.x, t2.x); + int txb = min(t0.y, t2.y); + int txr = max(t0.x, t2.x); + int txt = max(t0.y, t2.y); + if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) || + (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) { + LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle"); return false; } - if (dx[0] != -dx[2] || dy[1] != -dy[3]) { + if ((txl != 0) || (txb != 0) || + (txr != FIXED_ONE) || (txt != FIXED_ONE)) { + // we could probably handle this case, if we wanted to + LOGD_IF(DEBUG_COPYBIT, "texture is cropped"); return false; } - int x = sx[1]; - int y = sy[1]; - int w = dx[0]; - int h = dy[3]; - - // We expect the texture coordinates to always be the unit square: + // at this point, we know we are dealing with a rectangle, so we + // only need to consider 3 vertices for computing the jacobians + + const int dx01 = v1.x - v0.x; + const int dy01 = v1.y - v0.y; + const int dx02 = v2.x - v0.x; + const int dy02 = v2.y - v0.y; + const int ds01 = t1.S - t0.S; + const int dt01 = t1.T - t0.T; + const int ds02 = t2.S - t0.S; + const int dt02 = t2.T - t0.T; + const int area = dx01*dy02 - dy01*dx02; + int dsdx, dsdy, dtdx, dtdy; + if (area >= 0) { + dsdx = ds01*dy02 - ds02*dy01; + dsdy = ds02*dx01 - ds01*dx02; + dtdx = dt01*dy02 - dt02*dy01; + dtdy = dt02*dx01 - dt01*dx02; + } else { + dsdx = ds02*dy01 - ds01*dy02; + dsdy = ds01*dx02 - ds02*dx01; + dtdx = dt02*dy01 - dt01*dy02; + dtdy = dt01*dx02 - dt02*dx01; + } - static const GLfixed kExpectedUV[8] = { - 0, 0, - 0, FIXED_ONE, - FIXED_ONE, FIXED_ONE, - FIXED_ONE, 0 - }; - { - const GLfixed* pExpected = &kExpectedUV[0]; - for (int i = 0; i < 4; i++) { - GLfixed u = c->vc.vBuffer[i].texture[0].x; - GLfixed v = c->vc.vBuffer[i].texture[0].y; - if (u != *pExpected++ || v != *pExpected++) { - return false; - } - } + // here we rely on the fact that we know the transform is + // a rigid-body transform AND that it can only rotate in 90 degrees + // increments + + int transform = 0; + if (dsdx == 0) { + // 90 deg rotation case + // [ 0 dtdx ] + // [ dsdx 0 ] + transform |= COPYBIT_TRANSFORM_ROT_90; + // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted + if (dtdx > 0) + transform |= COPYBIT_TRANSFORM_FLIP_H; + if (dsdy < 0) + transform |= COPYBIT_TRANSFORM_FLIP_V; + } else { + // [ dsdx 0 ] + // [ 0 dtdy ] + if (dsdx < 0) + transform |= COPYBIT_TRANSFORM_FLIP_H; + if (dtdy < 0) + transform |= COPYBIT_TRANSFORM_FLIP_V; } - static const int tmu = 0; - texture_unit_t& u(c->textures.tmu[tmu]); - EGLTextureObject* textureObject = u.texture; + //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform); + //LOGD("A=%f\tB=%f\nC=%f\tD=%f", + // dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0); + int x = l >> 4; + int y = b >> 4; + int w = (r-l) >> 4; + int h = (t-b) >> 4; + texture_unit_t& u(c->textures.tmu[0]); + EGLTextureObject* textureObject = u.texture; GLint tWidth = textureObject->surface.width; GLint tHeight = textureObject->surface.height; GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight}; - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = cbSurface.height - (y + h); - - return copybit(x, y, w, h, textureObject, crop_rect, - COPYBIT_TRANSFORM_ROT_90, c); + return copybit(x, y, w, h, textureObject, crop_rect, transform, c); } /* @@ -357,17 +407,12 @@ bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, if ((w|h) <= 0) { return true; } - - if (! checkContext(c)) { + if (!checkContext(c)) { return false; } - - static const int tmu = 0; - texture_unit_t& u(c->textures.tmu[tmu]); + texture_unit_t& u(c->textures.tmu[0]); EGLTextureObject* textureObject = u.texture; - - return copybit(x, y, w, h, textureObject, textureObject->crop_rect, - 0, c); + return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c); } } // namespace android diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h index 401b68c2914a..b8b5afda2656 100644 --- a/opengl/libagl/copybit.h +++ b/opengl/libagl/copybit.h @@ -28,7 +28,8 @@ namespace android { bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c); -bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, + +bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count); inline bool copybitQuickCheckContext(ogles_context_t* c) { @@ -54,17 +55,16 @@ inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z, * Tries to draw a triangle fan using copybit hardware. * Returns true if successful. */ -inline bool drawTrangleFanWithCopybit(ogles_context_t* c, GLint first, +inline bool drawTriangleFanWithCopybit(ogles_context_t* c, GLint first, GLsizei count) { /* * We are looking for the glDrawArrays call made by SurfaceFlinger. */ - if (!(copybitQuickCheckContext(c) && first == 0 && count == 4)) { + if ((count!=4) || first || !copybitQuickCheckContext(c)) return false; - } - return drawTrangleFanWithCopybit_impl(c, first, count); + return drawTriangleFanWithCopybit_impl(c, first, count); } |