From 1473f46cbc82aa6f0ba744cc896a36923823d55b Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 10 Apr 2009 14:24:30 -0700 Subject: Integrate from //sandbox/mathias/donut/...@145728 SurfaceFlinger rework for new EGL driver model support. --- opengl/libagl/copybit.cpp | 370 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 opengl/libagl/copybit.cpp (limited to 'opengl/libagl/copybit.cpp') diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp new file mode 100644 index 000000000000..427e42aaf292 --- /dev/null +++ b/opengl/libagl/copybit.cpp @@ -0,0 +1,370 @@ +/* +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include +#include + +#include "context.h" +#include "fp.h" +#include "state.h" +#include "matrix.h" +#include "vertex.h" +#include "light.h" +#include "primitives.h" +#include "texture.h" +#include "BufferObjectManager.h" + +#include "TextureObjectManager.h" +#include +#include +#include "gralloc_priv.h" + +// ---------------------------------------------------------------------------- + +namespace android { + +static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) { + img->w = surface->stride; + img->h = surface->height; + img->format = surface->format; + img->offset = 0; + img->base = surface->data; + img->fd = fd; +} + +struct clipRectRegion : public copybit_region_t { + clipRectRegion(ogles_context_t* c) { + next = iterate; + int x = c->viewport.scissor.x; + int y = c->viewport.scissor.y; + r.l = x; + r.t = y; + r.r = x + c->viewport.scissor.w; + r.b = y + c->viewport.scissor.h; + firstTime = true; + } +private: + static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { + clipRectRegion* myself = (clipRectRegion*) self; + if (myself->firstTime) { + myself->firstTime = false; + *rect = myself->r; + return 1; + } + return 0; + } + mutable copybit_rect_t r; + mutable bool firstTime; +}; + +static bool supportedCopybitsFormat(int format) { + switch (format) { + case COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_RGB_565: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + case COPYBIT_FORMAT_YCbCr_422_SP: + case COPYBIT_FORMAT_YCbCr_420_SP: + return true; + default: + return false; + } +} + +static bool hasAlpha(int format) { + switch (format) { + case COPYBIT_FORMAT_RGBA_8888: + case COPYBIT_FORMAT_BGRA_8888: + case COPYBIT_FORMAT_RGBA_5551: + case COPYBIT_FORMAT_RGBA_4444: + return true; + default: + return false; + } +} + +static inline int fixedToByte(GGLfixed val) { + return (val - (val >> 8)) >> 8; +} + +/** + * Performs a quick check of the rendering state. If this function returns + * false we cannot use the copybit driver. + */ + +static bool checkContext(ogles_context_t* c) { + + // By convenction 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) { + return false; + } + + // Note: The drawSurfaceFd is only set for destination + // surfaces types that are supported by the hardware and + // do not have an alpha channel. So we don't have to re-check that here. + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + if (!supportedCopybitsFormat(textureObject->surface.format)) { + return false; + } + return true; +} + + +static bool copybit(GLint x, GLint y, + GLint w, GLint h, + EGLTextureObject* textureObject, + const GLint* crop_rect, + int transform, + ogles_context_t* c) +{ + // We assume checkContext has already been called and has already + // returned true. + + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; + + y = cbSurface.height - (y + h); + + const GLint Ucr = crop_rect[0]; + const GLint Vcr = crop_rect[1]; + const GLint Wcr = crop_rect[2]; + const GLint Hcr = crop_rect[3]; + + int32_t dsdx = (Wcr << 16) / w; // dsdx = ((Wcr/w)/Wt)*Wt + int32_t dtdy = ((-Hcr) << 16) / h; // dtdy = -((Hcr/h)/Ht)*Ht + + if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale + || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { + // The requested scale is out of the range the hardware + // can support. + return false; + } + + int32_t texelArea = gglMulx(dtdy, dsdx); + if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) { + // Non-linear filtering on a texture enlargement. + return false; + } + + if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) { + // Non-linear filtering on an texture shrink. + return false; + } + + const uint32_t enables = c->rasterizer.state.enables; + int planeAlpha = 255; + static const int tmu = 0; + texture_t& tev(c->rasterizer.state.texture[tmu]); + bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format); + switch (tev.env) { + + case GGL_REPLACE: + if (!srcTextureHasAlpha) { + planeAlpha = fixedToByte(c->currentColorClamped.a); + } + break; + + case GGL_MODULATE: + if (! (c->currentColorClamped.r == FIXED_ONE + && c->currentColorClamped.g == FIXED_ONE + && c->currentColorClamped.b == FIXED_ONE)) { + return false; + } + planeAlpha = fixedToByte(c->currentColorClamped.a); + break; + + default: + // Incompatible texture environment. + return false; + } + + bool blending = false; + + if ((enables & GGL_ENABLE_BLENDING) + && !(c->rasterizer.state.blend.src == GL_ONE + && c->rasterizer.state.blend.dst == GL_ZERO)) { + // Blending is OK if it is + // the exact kind of blending that the copybits hardware supports. + // Note: The hardware only supports + // GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA, + // But the surface flinger uses GL_ONE / GL_ONE_MINUS_SRC_ALPHA. + // We substitute GL_SRC_ALPHA / GL_ONE_MINUS_SRC_ALPHA in that case, + // because the performance is worth it, even if the results are + // not correct. + if (!((c->rasterizer.state.blend.src == GL_SRC_ALPHA + || c->rasterizer.state.blend.src == GL_ONE) + && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA + && c->rasterizer.state.blend.alpha_separate == 0)) { + // Incompatible blend mode. + return false; + } + blending = true; + } else { + // No blending is OK if we are not using alpha. + if (srcTextureHasAlpha || planeAlpha != 255) { + // Incompatible alpha + return false; + } + } + + if (srcTextureHasAlpha && planeAlpha != 255) { + // Can't do two types of alpha at once. + return false; + } + + // LOGW("calling copybits"); + + copybit_device_t* copybit = c->copybits.blitEngine; + copybit_image_t dst; + textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst); + copybit_rect_t drect = {x, y, x+w, y+h}; + + copybit_image_t src; + textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd, + &src); + copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr }; + + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); + + copybit->set_parameter(copybit, COPYBIT_DITHER, + (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE); + + clipRectRegion it(c); + copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + return true; +} + +/* + * 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)) { + 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]; + } + if (dx[1] | dx[3] | dy[0] | dy[2]) { + return false; + } + if (dx[0] != -dx[2] || dy[1] != -dy[3]) { + 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: + + 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; + } + } + } + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + 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); +} + +/* + * Try to drawTexiOESWithCopybit, return false if we fail. + */ + +bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, + GLint w, GLint h, ogles_context_t* c) +{ + // quickly process empty rects + if ((w|h) <= 0) { + return true; + } + + if (! checkContext(c)) { + return false; + } + + static const int tmu = 0; + texture_unit_t& u(c->textures.tmu[tmu]); + EGLTextureObject* textureObject = u.texture; + + return copybit(x, y, w, h, textureObject, textureObject->crop_rect, + 0, c); +} + +} // namespace android + -- cgit v1.2.3-59-g8ed1b From 350d651706d8f484d9aeb539d491526f822fa84a Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 10 Jun 2009 16:01:54 -0700 Subject: fix a bug where copybit only renders in the first buffer when used with s/w GL --- include/private/opengles/gl_context.h | 5 ++--- opengl/libagl/TextureObjectManager.cpp | 2 +- opengl/libagl/TextureObjectManager.h | 2 +- opengl/libagl/copybit.cpp | 27 +++++++++++++++++---------- opengl/libagl/copybit.h | 4 ++-- opengl/libagl/egl.cpp | 10 +++++----- opengl/libagl/state.cpp | 2 +- opengl/libagl/texture.cpp | 10 ++++------ opengl/tests/copybits/copybits.cpp | 16 +++++++--------- 9 files changed, 40 insertions(+), 38 deletions(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h index 641961f3a822..3b406779af5a 100644 --- a/include/private/opengles/gl_context.h +++ b/include/private/opengles/gl_context.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -600,9 +601,7 @@ struct copybits_context_t { copybit_device_t* blitEngine; int32_t minScale; int32_t maxScale; - // File descriptor of current drawing surface, if it's suitable for use as - // a copybits destination, else -1. - int drawSurfaceFd; + buffer_handle_t drawSurfaceBuffer; }; struct ogles_context_t { diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp index 9deb2cf9eea4..255ccac3565b 100644 --- a/opengl/libagl/TextureObjectManager.cpp +++ b/opengl/libagl/TextureObjectManager.cpp @@ -56,7 +56,7 @@ void EGLTextureObject::init() generate_mipmap = GL_FALSE; direct = GL_FALSE; #ifdef LIBAGL_USE_GRALLOC_COPYBITS - copybits_fd = -1; + try_copybit = false; #endif // LIBAGL_USE_GRALLOC_COPYBITS buffer = 0; } diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h index e0eadf147959..496e6947d737 100644 --- a/opengl/libagl/TextureObjectManager.h +++ b/opengl/libagl/TextureObjectManager.h @@ -80,7 +80,7 @@ public: GLint generate_mipmap; GLint direct; #ifdef LIBAGL_USE_GRALLOC_COPYBITS - int copybits_fd; + bool try_copybit; #endif // LIBAGL_USE_GRALLOC_COPYBITS android_native_buffer_t* buffer; }; diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index 427e42aaf292..a539a2bdd5d7 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -27,23 +27,28 @@ #include "primitives.h" #include "texture.h" #include "BufferObjectManager.h" - #include "TextureObjectManager.h" + #include #include +#include #include "gralloc_priv.h" // ---------------------------------------------------------------------------- namespace android { -static void textureToCopyBitImage(const GGLSurface* surface, int fd, copybit_image_t* img) { +static void textureToCopyBitImage( + const GGLSurface* surface, buffer_handle_t buffer, copybit_image_t* img) +{ + // we know private_handle_t is good here + private_handle_t* hnd = (private_handle_t*)buffer; img->w = surface->stride; img->h = surface->height; img->format = surface->format; - img->offset = 0; + img->offset = hnd->offset; img->base = surface->data; - img->fd = fd; + img->fd = hnd->fd; } struct clipRectRegion : public copybit_region_t { @@ -109,7 +114,7 @@ static inline int fixedToByte(GGLfixed val) { static bool checkContext(ogles_context_t* c) { - // By convenction copybitQuickCheckContext() has already returned true. + // By convention copybitQuickCheckContext() has already returned true. // avoid checking the same information again. if (c->copybits.blitEngine == NULL @@ -118,7 +123,7 @@ static bool checkContext(ogles_context_t* c) { return false; } - // Note: The drawSurfaceFd is only set for destination + // Note: The drawSurfaceBuffer is only set for destination // surfaces types that are supported by the hardware and // do not have an alpha channel. So we don't have to re-check that here. @@ -237,18 +242,20 @@ static bool copybit(GLint x, GLint y, // LOGW("calling copybits"); copybit_device_t* copybit = c->copybits.blitEngine; + copybit_image_t dst; - textureToCopyBitImage(&cbSurface, c->copybits.drawSurfaceFd, &dst); + buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer; + textureToCopyBitImage(&cbSurface, target_hnd, &dst); copybit_rect_t drect = {x, y, x+w, y+h}; + // we know private_handle_t is good here copybit_image_t src; - textureToCopyBitImage(&textureObject->surface, textureObject->copybits_fd, - &src); + buffer_handle_t source_hnd = textureObject->buffer->handle; + textureToCopyBitImage(&textureObject->surface, source_hnd, &src); copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr }; copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE); diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h index 1888aee1929e..401b68c2914a 100644 --- a/opengl/libagl/copybit.h +++ b/opengl/libagl/copybit.h @@ -32,9 +32,9 @@ bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count); inline bool copybitQuickCheckContext(ogles_context_t* c) { - return c->copybits.drawSurfaceFd >= 0 + return c->copybits.drawSurfaceBuffer != 0 && c->rasterizer.state.enabled_tmu == 1 - && c->textures.tmu[0].texture->copybits_fd >= 0; + && c->textures.tmu[0].texture->try_copybit; } /* diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 0df2bbaa584f..c6d50578869a 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -551,20 +551,20 @@ EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) gl->rasterizer.procs.depthBuffer(gl, &depth); + #ifdef LIBAGL_USE_GRALLOC_COPYBITS - gl->copybits.drawSurfaceFd = -1; + gl->copybits.drawSurfaceBuffer = 0; if (supportedCopybitsDestinationFormat(buffer.format)) { buffer_handle_t handle = this->buffer->handle; if (handle != NULL) { private_handle_t* hand = private_handle_t::dynamicCast(handle); - if (hand != NULL) { - if (hand->usesPhysicallyContiguousMemory()) { - gl->copybits.drawSurfaceFd = hand->fd; - } + if (hand != NULL && hand->usesPhysicallyContiguousMemory()) { + gl->copybits.drawSurfaceBuffer = handle; } } } #endif // LIBAGL_USE_GRALLOC_COPYBITS + return EGL_TRUE; } EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp index a00f779d6d35..a59b3b046e3f 100644 --- a/opengl/libagl/state.cpp +++ b/opengl/libagl/state.cpp @@ -101,7 +101,7 @@ ogles_context_t *ogles_init(size_t extra) c->copybits.blitEngine = NULL; c->copybits.minScale = 0; c->copybits.maxScale = 0; - c->copybits.drawSurfaceFd = -1; + c->copybits.drawSurfaceBuffer = 0; #ifdef LIBAGL_USE_GRALLOC_COPYBITS hw_module_t const* module; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index d675107ca0b1..05fd46e5a2b0 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -1544,12 +1544,10 @@ void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) * */ #ifdef LIBAGL_USE_GRALLOC_COPYBITS - tex->copybits_fd = -1; - private_handle_t* hand; - if ((hand = private_handle_t::dynamicCast(native_buffer->handle)) != NULL) { - if (hand->usesPhysicallyContiguousMemory()) { - tex->copybits_fd = hand->fd; - } + tex->try_copybit = false; + private_handle_t* hnd = private_handle_t::dynamicCast(native_buffer->handle); + if (hnd && hnd->usesPhysicallyContiguousMemory()) { + tex->try_copybit = true; } #endif // LIBAGL_USE_GRALLOC_COPYBITS } diff --git a/opengl/tests/copybits/copybits.cpp b/opengl/tests/copybits/copybits.cpp index d15526c65e94..f8ca9b2e0eee 100644 --- a/opengl/tests/copybits/copybits.cpp +++ b/opengl/tests/copybits/copybits.cpp @@ -96,13 +96,11 @@ private: status_t initSize(uint32_t w, uint32_t h); ssize_t mInitCheck; - uint32_t mFlags; - uint32_t mVStride; void* mData; }; Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) - : SurfaceBuffer(), mInitCheck(NO_INIT), mVStride(0) + : SurfaceBuffer(), mInitCheck(NO_INIT) { this->usage = usage; this->format = format; @@ -137,7 +135,6 @@ status_t Buffer::initSize(uint32_t w, uint32_t h) if (err == NO_ERROR) { width = w; height = h; - mVStride = 0; } } @@ -154,7 +151,6 @@ status_t Buffer::lock(GGLSurface* sur, uint32_t usage) sur->height = height; sur->stride = stride; sur->format = format; - sur->vstride = mVStride; sur->data = static_cast(vaddr); } return res; @@ -355,7 +351,7 @@ void init_scene(void) // #define USE_ALPHA_COLOR #define USE_GL_REPLACE -// #define USE_GL_MODULATE +//#define USE_GL_MODULATE // #define USE_BLEND @@ -479,7 +475,7 @@ static const int SCALE_COUNT = 12; int scale(int base, int factor) { static const float kTable[SCALE_COUNT] = { - 0.1f, 0.25f, 0.5f, 0.75f, 1.0f, + 0.24f, 0.25f, 0.5f, 0.75f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 5.0f }; return base * kTable[factor]; @@ -570,10 +566,10 @@ int testStretch() return -1; } // Need to do a dummy eglSwapBuffers first. Don't know why. - glClearColor(0.4, 1.0, 0.4, 0.4); + glClearColor(0.4, 1.0, 0.4, 1.0); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); eglSwapBuffers(eglDisplay, eglSurface); - + int cropRect[4] = {0,HEIGHT,WIDTH,-HEIGHT}; // Left bottom width height. Width and Height can be neg to flip. glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect); @@ -592,6 +588,8 @@ int testStretch() } eglSwapBuffers(eglDisplay, eglSurface); + LOGD("wait 1s"); + usleep(1000000); } return 0; } -- cgit v1.2.3-59-g8ed1b From 4d63fb113b542f0474c16d8f2c8a1240b44f0ca2 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 16 Jun 2009 18:08:29 -0700 Subject: fix a scissor bug in the GLES-on-top-of copybit code --- opengl/libagl/copybit.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index a539a2bdd5d7..d57a6e429081 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -52,28 +52,25 @@ static void textureToCopyBitImage( } struct clipRectRegion : public copybit_region_t { - clipRectRegion(ogles_context_t* c) { - next = iterate; - int x = c->viewport.scissor.x; - int y = c->viewport.scissor.y; - r.l = x; - r.t = y; - r.r = x + c->viewport.scissor.w; - r.b = y + c->viewport.scissor.h; - firstTime = true; + clipRectRegion(ogles_context_t* c) + { + scissor_t const* scissor = &c->rasterizer.state.scissor; + r.l = scissor->left; + r.t = scissor->top; + r.r = scissor->right; + r.b = scissor->bottom; + next = iterate; } private: static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { - clipRectRegion* myself = (clipRectRegion*) self; - if (myself->firstTime) { - myself->firstTime = false; - *rect = myself->r; - return 1; - } + *rect = static_cast(self)->r; + const_cast(self)->next = iterate_done; + return 1; + } + static int iterate_done(copybit_region_t const *, copybit_rect_t*) { return 0; } - mutable copybit_rect_t r; - mutable bool firstTime; + copybit_rect_t r; }; static bool supportedCopybitsFormat(int format) { -- cgit v1.2.3-59-g8ed1b From 03a1b0116b115c214c16fa1a02a46999312fd0f2 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 17 Jun 2009 21:18:56 -0700 Subject: 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. --- opengl/libagl/array.cpp | 2 +- opengl/libagl/copybit.cpp | 187 ++++++++++++++++++++++++++++------------------ opengl/libagl/copybit.h | 10 +-- 3 files changed, 122 insertions(+), 77 deletions(-) (limited to 'opengl/libagl/copybit.cpp') 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 #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); } -- cgit v1.2.3-59-g8ed1b From 42bf621e801183028066e6947fdd22eae8693a02 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 17 Jun 2009 21:58:18 -0700 Subject: fix/add some comments --- opengl/libagl/copybit.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index 0736b6b7b374..a663f75d34eb 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -175,21 +175,24 @@ static bool copybit(GLint x, GLint y, return false; } - /* + // copybit doesn't say anything about filtering, so we can't + // discriminate. On msm7k, copybit will always filter. + // the code below handles min/mag filters, we keep it as a reference. + +#ifdef MIN_MAG_FILTER 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; } - */ - +#endif + const uint32_t enables = c->rasterizer.state.enables; int planeAlpha = 255; static const int tmu = 0; @@ -295,6 +298,11 @@ bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei co // we detect if we're dealing with a rectangle, by comparing the // rectangles {v0,v2} and {v1,v3} which should be identical. + // NOTE: we should check that the rectangle is window aligned, however + // if we do that, the optimization won't be taken in a lot of cases. + // Since this code is intended to be used with SurfaceFlinger only, + // so it's okay... + 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; -- cgit v1.2.3-59-g8ed1b From 09cf0ac2e9ec9e18c7099312265f9d51cdbb0f37 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 18 Jun 2009 19:31:07 -0700 Subject: we were not fetching the texture coords in the copybit case, so we were using garbage --- opengl/libagl/copybit.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index a663f75d34eb..cde8f8a68af8 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -293,6 +293,7 @@ bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei co return false; } + // FIXME: we should handle culling here c->arrays.compileElements(c, c->vc.vBuffer, 0, 4); // we detect if we're dealing with a rectangle, by comparing the @@ -316,6 +317,18 @@ bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei co LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle"); return false; } + + // fetch and transform texture coordinates + // NOTE: maybe it would be better to have a "compileElementsAll" method + // that would ensure all vertex data are fetched and transformed + const transform_t& tr = c->transforms.texture[0].transform; + for (size_t i=0 ; i<4 ; i++) { + const GLubyte* tp = c->arrays.texture[0].element(i); + vertex_t* const v = &c->vc.vBuffer[i]; + c->arrays.texture[0].fetch(c, v->texture[0].v, tp); + // FIXME: we should bail if q!=1 + c->arrays.tex_transform[0](&tr, &v->texture[0], &v->texture[0]); + } const vec4_t& t0 = c->vc.vBuffer[0].texture[0]; const vec4_t& t1 = c->vc.vBuffer[1].texture[0]; @@ -333,7 +346,8 @@ bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei co 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"); + LOGD_IF(DEBUG_COPYBIT, "texture is cropped: %08x,%08x,%08x,%08x", + txl, txb, txr, txt); return false; } -- cgit v1.2.3-59-g8ed1b From f6c2a1ae60a190951b1c9e93f64f62a000cb51fd Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 23 Jun 2009 18:31:06 -0700 Subject: fix a bug where copybit would be rejected in landscape mode --- opengl/libagl/copybit.cpp | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index cde8f8a68af8..093a32d6d488 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -163,15 +163,23 @@ static bool copybit(GLint x, GLint y, const GLint Wcr = crop_rect[2]; const GLint Hcr = crop_rect[3]; - int32_t dsdx = (Wcr << 16) / w; // dsdx = ((Wcr/w)/Wt)*Wt - int32_t dtdy = ((-Hcr) << 16) / h; // dtdy = -((Hcr/h)/Ht)*Ht - + int32_t dsdx = (Wcr << 16); // dsdx = ((Wcr/w)/Wt)*Wt + int32_t dtdy = ((-Hcr) << 16); // dtdy = -((Hcr/h)/Ht)*Ht + if (transform & COPYBIT_TRANSFORM_ROT_90) { + dsdx /= h; + dtdy /= w; + } else { + dsdx /= w; + dtdy /= h; + } if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale || 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); + "scale out of range dsdx=%08x (Wcr=%d / w=%d), " + "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d", + dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr); return false; } @@ -198,22 +206,30 @@ static bool copybit(GLint x, GLint y, static const int tmu = 0; texture_t& tev(c->rasterizer.state.texture[tmu]); bool srcTextureHasAlpha = hasAlpha(textureObject->surface.format); - switch (tev.env) { + if (!srcTextureHasAlpha) { + planeAlpha = fixedToByte(c->currentColorClamped.a); + } + switch (tev.env) { case GGL_REPLACE: - if (!srcTextureHasAlpha) { - planeAlpha = fixedToByte(c->currentColorClamped.a); - } break; - case GGL_MODULATE: - 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"); + 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 (%08x, %08x, %08x)", + c->currentColorClamped.r, + c->currentColorClamped.g, + c->currentColorClamped.b); + return false; + } + if (srcTextureHasAlpha && c->currentColorClamped.a < FIXED_ONE) { + LOGD_IF(DEBUG_COPYBIT, + "MODULATE and texture w/alpha and alpha=%08x)", + c->currentColorClamped.a); return false; } - planeAlpha = fixedToByte(c->currentColorClamped.a); break; default: @@ -223,7 +239,6 @@ static bool copybit(GLint x, GLint y, } bool blending = false; - if ((enables & GGL_ENABLE_BLENDING) && !(c->rasterizer.state.blend.src == GL_ONE && c->rasterizer.state.blend.dst == GL_ZERO)) { -- cgit v1.2.3-59-g8ed1b From 2eab9d8d7034ef05cead1ee26667a75061b5f0aa Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 24 Jun 2009 16:55:59 -0700 Subject: copybit now uses a native_handle_t* instead of a fd/offset --- libs/surfaceflinger/Android.mk | 2 + libs/surfaceflinger/LayerBuffer.cpp | 86 +++++++++++++++++++------------------ opengl/libagl/copybit.cpp | 7 +-- 3 files changed, 47 insertions(+), 48 deletions(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 29b88e9f5640..f718e7ada692 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -47,6 +47,8 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_C_INCLUDES := \ $(call include-path-for, corecg graphics) +LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc + LOCAL_MODULE:= libsurfaceflinger include $(BUILD_SHARED_LIBRARY) diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 1baf720b1e7b..58bba44a0459 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -32,6 +32,7 @@ #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" +#include "gralloc_priv.h" // needed for msm / copybit namespace android { @@ -233,20 +234,28 @@ LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset) : mBufferHeap(buffers) { NativeBuffer& src(mNativeBuffer); + src.crop.l = 0; src.crop.t = 0; src.crop.r = buffers.w; src.crop.b = buffers.h; - src.img.w = buffers.hor_stride ?: buffers.w; - src.img.h = buffers.ver_stride ?: buffers.h; - src.img.format = buffers.format; - src.img.offset = offset; - src.img.base = buffers.heap->base(); - src.img.fd = buffers.heap->heapID(); + + src.img.w = buffers.hor_stride ?: buffers.w; + src.img.h = buffers.ver_stride ?: buffers.h; + src.img.format = buffers.format; + src.img.base = (void*)(intptr_t(buffers.heap->base()) + offset); + + private_handle_t* hnd = new private_handle_t( + buffers.heap->heapID(), buffers.heap->getSize(), 0); + hnd->offset = offset; + src.img.handle = hnd; } LayerBuffer::Buffer::~Buffer() { + NativeBuffer& src(mNativeBuffer); + if (src.img.handle) + delete (private_handle_t*)src.img.handle; } // ============================================================================ @@ -465,45 +474,38 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const android_native_buffer_t const* nb = fbw->getBackbuffer(); native_handle_t const* hnd = nb->handle; - if (hnd->data[1] != 0x3141592) { - LOGE("buffer not compatible with copybit"); - err = -1; - } else { + dst.w = 320; + dst.h = 480; + dst.format = 4; + dst.base = 0; + dst.handle = (native_handle_t *)nb->handle; - dst.w = 320; - dst.h = 480; - dst.format = 4; - dst.offset = hnd->data[4]; - dst.base = 0; - dst.fd = hnd->data[0]; - - const Rect& transformedBounds = mLayer.getTransformedBounds(); - const copybit_rect_t& drect + const Rect& transformedBounds = mLayer.getTransformedBounds(); + const copybit_rect_t& drect = reinterpret_cast(transformedBounds); - const State& s(mLayer.drawingState()); - region_iterator it(clip); - - // pick the right orientation for this buffer - int orientation = mLayer.getOrientation(); - if (UNLIKELY(mBufferHeap.transform)) { - Transform rot90; - GraphicPlane::orientationToTransfrom( - ISurfaceComposer::eOrientation90, 0, 0, &rot90); - const Transform& planeTransform(mLayer.graphicPlane(0).transform()); - const Layer::State& s(mLayer.drawingState()); - Transform tr(planeTransform * s.transform * rot90); - orientation = tr.getOrientation(); - } + const State& s(mLayer.drawingState()); + region_iterator it(clip); + + // pick the right orientation for this buffer + int orientation = mLayer.getOrientation(); + if (UNLIKELY(mBufferHeap.transform)) { + Transform rot90; + GraphicPlane::orientationToTransfrom( + ISurfaceComposer::eOrientation90, 0, 0, &rot90); + const Transform& planeTransform(mLayer.graphicPlane(0).transform()); + const Layer::State& s(mLayer.drawingState()); + Transform tr(planeTransform * s.transform * rot90); + orientation = tr.getOrientation(); + } - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); - copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); - err = copybit->stretch(copybit, - &dst, &src.img, &drect, &src.crop, &it); - if (err != NO_ERROR) { - LOGE("copybit failed (%s)", strerror(err)); - } + err = copybit->stretch(copybit, + &dst, &src.img, &drect, &src.crop, &it); + if (err != NO_ERROR) { + LOGE("copybit failed (%s)", strerror(err)); } } @@ -522,7 +524,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const t.stride = src.img.w; t.vstride= src.img.h; t.format = src.img.format; - t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); + t.data = (GGLubyte*)src.img.base; const Region dirty(Rect(t.width, t.height)); mLayer.loadTexture(&mTexture, mTexture.name, dirty, t); mTexture.transform = mBufferHeap.transform; diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index 093a32d6d488..b6dedaeb5978 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -32,7 +32,6 @@ #include #include #include -#include "gralloc_priv.h" #define DEBUG_COPYBIT true @@ -44,14 +43,11 @@ namespace android { static void textureToCopyBitImage( const GGLSurface* surface, buffer_handle_t buffer, copybit_image_t* img) { - // we know private_handle_t is good here - private_handle_t* hnd = (private_handle_t*)buffer; img->w = surface->stride; img->h = surface->height; img->format = surface->format; - img->offset = hnd->offset; img->base = surface->data; - img->fd = hnd->fd; + img->handle = (native_handle_t *)buffer; } struct clipRectRegion : public copybit_region_t { @@ -283,7 +279,6 @@ static bool copybit(GLint x, GLint y, textureToCopyBitImage(&cbSurface, target_hnd, &dst); copybit_rect_t drect = {x, y, x+w, y+h}; - // we know private_handle_t is good here copybit_image_t src; buffer_handle_t source_hnd = textureObject->buffer->handle; textureToCopyBitImage(&textureObject->surface, source_hnd, &src); -- cgit v1.2.3-59-g8ed1b From 0f53af13b783eafa566722eb118aabcb84d88da5 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 29 Jun 2009 16:36:49 -0700 Subject: fix a bug where gl didn't always fallback to software when copybit failed. minor optimizations to copybit codepath. --- opengl/libagl/copybit.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'opengl/libagl/copybit.cpp') diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index b6dedaeb5978..3331026f66b9 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -159,15 +159,19 @@ static bool copybit(GLint x, GLint y, const GLint Wcr = crop_rect[2]; const GLint Hcr = crop_rect[3]; - int32_t dsdx = (Wcr << 16); // dsdx = ((Wcr/w)/Wt)*Wt - int32_t dtdy = ((-Hcr) << 16); // dtdy = -((Hcr/h)/Ht)*Ht + GLint screen_w = w; + GLint screen_h = h; + int32_t dsdx = Wcr << 16; // dsdx = ((Wcr/screen_w)/Wt)*Wt + int32_t dtdy = Hcr << 16; // dtdy = -((Hcr/screen_h)/Ht)*Ht if (transform & COPYBIT_TRANSFORM_ROT_90) { - dsdx /= h; - dtdy /= w; - } else { - dsdx /= w; - dtdy /= h; + swap(screen_w, screen_h); + } + if (dsdx!=screen_w || dtdy!=screen_h) { + // in most cases the divide is not needed + dsdx /= screen_w; + dtdy /= screen_h; } + dtdy = -dtdy; // see equation of dtdy above if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { // The requested scale is out of the range the hardware @@ -290,8 +294,8 @@ static bool copybit(GLint x, GLint y, (enables & GGL_ENABLE_DITHER) ? COPYBIT_ENABLE : COPYBIT_DISABLE); clipRectRegion it(c); - copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); - return true; + status_t err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + return err == NO_ERROR ? true : false; } /* @@ -365,24 +369,24 @@ bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei co // 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 dy01 = v1.y - v0.y; 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 dt01 = t1.T - t0.T; 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; + dsdy = ds02*dx01 - ds01*dx02; dtdy = dt02*dx01 - dt01*dx02; } else { dsdx = ds02*dy01 - ds01*dy02; - dsdy = ds01*dx02 - ds02*dx01; dtdx = dt02*dy01 - dt01*dy02; + dsdy = ds01*dx02 - ds02*dx01; dtdy = dt01*dx02 - dt02*dx01; } -- cgit v1.2.3-59-g8ed1b