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/egl.cpp | 425 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 303 insertions(+), 122 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 3b4c0419f0db..5c91c92bb1db 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -1,22 +1,20 @@ -/* +/* ** ** Copyright 2007 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 +** 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 +** 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 +** 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. */ -#define LOG_TAG "EGL" - #include #include #include @@ -35,6 +33,7 @@ #include #include +#include #include #include @@ -46,6 +45,10 @@ #include "texture.h" #include "matrix.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "gralloc_priv.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS + #undef NELEM #define NELEM(x) (sizeof(x)/sizeof(*(x))) @@ -89,9 +92,9 @@ static GLint getError() { struct egl_display_t { egl_display_t() : type(0), initialized(0) { } - + static egl_display_t& get_display(EGLDisplay dpy); - + static EGLBoolean is_valid(EGLDisplay dpy) { return ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) ? EGL_FALSE : EGL_TRUE; } @@ -140,7 +143,7 @@ struct egl_surface_t egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat); virtual ~egl_surface_t(); virtual bool isValid() const = 0; - + virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; virtual EGLint getWidth() const = 0; @@ -188,39 +191,48 @@ EGLint egl_surface_t::getSwapBehavior() const { // ---------------------------------------------------------------------------- -struct egl_window_surface_t : public egl_surface_t +struct egl_window_surface_v2_t : public egl_surface_t { - egl_window_surface_t( + egl_window_surface_v2_t( EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - egl_native_window_t* window); + android_native_window_t* window); - ~egl_window_surface_t(); + ~egl_window_surface_v2_t(); - virtual bool isValid() const { return nativeWindow->magic == 0x600913; } + virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; } virtual EGLBoolean swapBuffers(); virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); - virtual EGLint getWidth() const { return nativeWindow->width; } - virtual EGLint getHeight() const { return nativeWindow->height; } + virtual EGLint getWidth() const { return buffer->width; } + virtual EGLint getHeight() const { return buffer->height; } virtual void* getBits() const; virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; private: - egl_native_window_t* nativeWindow; + android_native_window_t* nativeWindow; + android_native_buffer_t* buffer; + int width; + int height; }; -egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, +egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat, - egl_native_window_t* window) - : egl_surface_t(dpy, config, depthFormat), nativeWindow(window) + android_native_window_t* window) + : egl_surface_t(dpy, config, depthFormat), nativeWindow(window), buffer(0) { + nativeWindow->common.incRef(&nativeWindow->common); + + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + + width = buffer->width; + height = buffer->height; if (depthFormat) { - depth.width = window->width; - depth.height = window->height; + depth.width = width; + depth.height = height; depth.stride = depth.width; // use the width here depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { @@ -228,23 +240,56 @@ egl_window_surface_t::egl_window_surface_t(EGLDisplay dpy, return; } } - nativeWindow->incRef(nativeWindow); + + // TODO: lockBuffer should rather be executed when the very first + // direct rendering occurs. + buffer->common.incRef(&buffer->common); + nativeWindow->lockBuffer(nativeWindow, buffer); + + // FIXME: we need to gralloc lock the buffer + // FIXME: we need to handle the copy-back if needed, but + // for now we're a "non preserving" implementation. } -egl_window_surface_t::~egl_window_surface_t() { - nativeWindow->decRef(nativeWindow); + +egl_window_surface_v2_t::~egl_window_surface_v2_t() { + if (buffer) { + buffer->common.decRef(&buffer->common); + } + nativeWindow->common.decRef(&nativeWindow->common); } -EGLBoolean egl_window_surface_t::swapBuffers() +EGLBoolean egl_window_surface_v2_t::swapBuffers() { - uint32_t flags = nativeWindow->swapBuffers(nativeWindow); - if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) { + // TODO: this is roughly the code needed for preserving the back buffer + // efficiently. dirty is the area that has been modified. + //Region newDirty(dirty); + //newDirty.andSelf(Rect(nativeWindow->width, nativeWindow->height)); + //mDirty = newDirty; + //const Region copyback(mDirty.subtract(newDirty)); + //mDisplaySurface->copyFrontToBack(copyback); + + + nativeWindow->queueBuffer(nativeWindow, buffer); + buffer->common.decRef(&buffer->common); buffer = 0; + + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + buffer->common.incRef(&buffer->common); + + // TODO: lockBuffer should rather be executed when the very first + // direct rendering occurs. + nativeWindow->lockBuffer(nativeWindow, buffer); + + + if ((width != buffer->width) || (height != buffer->height)) { // TODO: we probably should reset the swap rect here // if the window size has changed + width = buffer->width; + height = buffer->height; if (depth.data) { free(depth.data); - depth.width = nativeWindow->width; - depth.height = nativeWindow->height; - depth.stride = nativeWindow->stride; + depth.width = width; + depth.height = height; + depth.stride = buffer->stride; depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); @@ -255,49 +300,81 @@ EGLBoolean egl_window_surface_t::swapBuffers() return EGL_TRUE; } -EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl) +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + +static bool supportedCopybitsDestinationFormat(int format) { + // Hardware supported and no destination alpha + switch (format) { + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return true; + default: + return false; + } +} +#endif + +EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) { GGLSurface buffer; buffer.version = sizeof(GGLSurface); - buffer.width = nativeWindow->width; - buffer.height = nativeWindow->height; - buffer.stride = nativeWindow->stride; - buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; - buffer.format = nativeWindow->format; + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)this->buffer->bits; + buffer.format = this->buffer->format; 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; + if (supportedCopybitsDestinationFormat(buffer.format)) { + buffer_handle_t handle; + this->buffer->getHandle(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; + } + } + } + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS return EGL_TRUE; } -EGLBoolean egl_window_surface_t::bindReadSurface(ogles_context_t* gl) +EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) { GGLSurface buffer; buffer.version = sizeof(GGLSurface); - buffer.width = nativeWindow->width; - buffer.height = nativeWindow->height; - buffer.stride = nativeWindow->stride; - buffer.data = (GGLubyte*)nativeWindow->base + nativeWindow->offset; - buffer.format = nativeWindow->format; + buffer.width = this->buffer->width; + buffer.height = this->buffer->height; + buffer.stride = this->buffer->stride; + buffer.data = (GGLubyte*)this->buffer->bits; + buffer.format = this->buffer->format; gl->rasterizer.procs.readBuffer(gl, &buffer); return EGL_TRUE; } -void* egl_window_surface_t::getBits() const { - return (GGLubyte*)nativeWindow->base + nativeWindow->offset; +void* egl_window_surface_v2_t::getBits() const { + return (GGLubyte*)buffer->bits; } -EGLint egl_window_surface_t::getHorizontalResolution() const { +EGLint egl_window_surface_v2_t::getHorizontalResolution() const { return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } -EGLint egl_window_surface_t::getVerticalResolution() const { +EGLint egl_window_surface_v2_t::getVerticalResolution() const { return (nativeWindow->ydpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } -EGLint egl_window_surface_t::getRefreshRate() const { - return (nativeWindow->fps * EGL_DISPLAY_SCALING); +EGLint egl_window_surface_v2_t::getRefreshRate() const { + return (60 * EGL_DISPLAY_SCALING); // FIXME } -EGLint egl_window_surface_t::getSwapBehavior() const { - uint32_t flags = nativeWindow->flags; - if (flags & EGL_NATIVES_FLAG_DESTROY_BACKBUFFER) - return EGL_BUFFER_DESTROYED; - return EGL_BUFFER_PRESERVED; +EGLint egl_window_surface_v2_t::getSwapBehavior() const { + //uint32_t flags = nativeWindow->flags; + //if (flags & SURFACE_FLAG_PRESERVE_CONTENT) + // return EGL_BUFFER_PRESERVED; + // This is now a feature of EGL, currently we don't preserve + // the content of the buffers. + return EGL_BUFFER_DESTROYED; } // ---------------------------------------------------------------------------- @@ -311,7 +388,7 @@ struct egl_pixmap_surface_t : public egl_surface_t virtual ~egl_pixmap_surface_t() { } - virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } + virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); } virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return nativePixmap.width; } @@ -347,7 +424,7 @@ EGLBoolean egl_pixmap_surface_t::bindDrawSurface(ogles_context_t* gl) buffer.stride = nativePixmap.stride; buffer.data = nativePixmap.data; buffer.format = nativePixmap.format; - + gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) gl->rasterizer.procs.depthBuffer(gl, &depth); @@ -376,7 +453,7 @@ struct egl_pbuffer_surface_t : public egl_surface_t virtual ~egl_pbuffer_surface_t(); - virtual bool isValid() const { return pbuffer.data != 0; } + virtual bool isValid() const { return pbuffer.data != 0; } virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return pbuffer.width; } @@ -407,7 +484,7 @@ egl_pbuffer_surface_t::egl_pbuffer_surface_t(EGLDisplay dpy, pbuffer.stride = w; pbuffer.data = (GGLubyte*)malloc(size); pbuffer.format = f; - + if (depthFormat) { depth.width = pbuffer.width; depth.height = pbuffer.height; @@ -468,7 +545,11 @@ struct config_management_t { static char const * const gVendorString = "Google Inc."; static char const * const gVersionString = "1.2 Android Driver"; static char const * const gClientApiString = "OpenGL ES"; -static char const * const gExtensionsString = ""; +static char const * const gExtensionsString = + "KHR_image_base " + // "KHR_image_pixmap " + "EGL_ANDROID_image_native_buffer " + ; // ---------------------------------------------------------------------------- @@ -478,25 +559,45 @@ struct extention_map_t { }; static const extention_map_t gExtentionMap[] = { - { "glDrawTexsOES", (void(*)())&glDrawTexsOES }, - { "glDrawTexiOES", (void(*)())&glDrawTexiOES }, - { "glDrawTexfOES", (void(*)())&glDrawTexfOES }, - { "glDrawTexxOES", (void(*)())&glDrawTexxOES }, - { "glDrawTexsvOES", (void(*)())&glDrawTexsvOES }, - { "glDrawTexivOES", (void(*)())&glDrawTexivOES }, - { "glDrawTexfvOES", (void(*)())&glDrawTexfvOES }, - { "glDrawTexxvOES", (void(*)())&glDrawTexxvOES }, - { "glQueryMatrixxOES", (void(*)())&glQueryMatrixxOES }, - { "glClipPlanef", (void(*)())&glClipPlanef }, - { "glClipPlanex", (void(*)())&glClipPlanex }, - { "glBindBuffer", (void(*)())&glBindBuffer }, - { "glBufferData", (void(*)())&glBufferData }, - { "glBufferSubData", (void(*)())&glBufferSubData }, - { "glDeleteBuffers", (void(*)())&glDeleteBuffers }, - { "glGenBuffers", (void(*)())&glGenBuffers }, + { "glDrawTexsOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexsOES }, + { "glDrawTexiOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexiOES }, + { "glDrawTexfOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexfOES }, + { "glDrawTexxOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexxOES }, + { "glDrawTexsvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexsvOES }, + { "glDrawTexivOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexivOES }, + { "glDrawTexfvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexfvOES }, + { "glDrawTexxvOES", + (__eglMustCastToProperFunctionPointerType)&glDrawTexxvOES }, + { "glQueryMatrixxOES", + (__eglMustCastToProperFunctionPointerType)&glQueryMatrixxOES }, + { "glEGLImageTargetTexture2DOES", + (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetTexture2DOES }, + { "glEGLImageTargetRenderbufferStorageOES", + (__eglMustCastToProperFunctionPointerType)&glEGLImageTargetRenderbufferStorageOES }, + { "glClipPlanef", + (__eglMustCastToProperFunctionPointerType)&glClipPlanef }, + { "glClipPlanex", + (__eglMustCastToProperFunctionPointerType)&glClipPlanex }, + { "glBindBuffer", + (__eglMustCastToProperFunctionPointerType)&glBindBuffer }, + { "glBufferData", + (__eglMustCastToProperFunctionPointerType)&glBufferData }, + { "glBufferSubData", + (__eglMustCastToProperFunctionPointerType)&glBufferSubData }, + { "glDeleteBuffers", + (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, + { "glGenBuffers", + (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, }; -/* +/* * In the lists below, attributes names MUST be sorted. * Additionally, all configs must be sorted according to * the EGL specification. @@ -507,7 +608,7 @@ static config_pair_t const config_base_attribute_list[] = { { EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG }, { EGL_LEVEL, 0 }, { EGL_MAX_PBUFFER_HEIGHT, GGL_MAX_VIEWPORT_DIMS }, - { EGL_MAX_PBUFFER_PIXELS, + { EGL_MAX_PBUFFER_PIXELS, GGL_MAX_VIEWPORT_DIMS*GGL_MAX_VIEWPORT_DIMS }, { EGL_MAX_PBUFFER_WIDTH, GGL_MAX_VIEWPORT_DIMS }, { EGL_NATIVE_RENDERABLE, EGL_TRUE }, @@ -644,9 +745,9 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key) { while (first <= last) { int mid = (first + last) / 2; - if (key > sortedArray[mid].key) { + if (key > sortedArray[mid].key) { first = mid + 1; - } else if (key < sortedArray[mid].key) { + } else if (key < sortedArray[mid].key) { last = mid - 1; } else { return mid; @@ -658,13 +759,13 @@ static int binarySearch(T const sortedArray[], int first, int last, EGLint key) static int isAttributeMatching(int i, EGLint attr, EGLint val) { // look for the attribute in all of our configs - config_pair_t const* configFound = gConfigs[i].array; + config_pair_t const* configFound = gConfigs[i].array; int index = binarySearch( gConfigs[i].array, 0, gConfigs[i].size-1, attr); if (index < 0) { - configFound = config_base_attribute_list; + configFound = config_base_attribute_list; index = binarySearch( config_base_attribute_list, 0, NELEM(config_base_attribute_list)-1, @@ -778,28 +879,28 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -812,9 +913,9 @@ static EGLSurface createWindowSurface(EGLDisplay dpy, EGLConfig config, //if (EGLint(info.format) != pixelFormat) // return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - egl_surface_t* surface = - new egl_window_surface_t(dpy, config, depthFormat, - static_cast(window)); + egl_surface_t* surface; + surface = new egl_window_surface_v2_t(dpy, config, depthFormat, + static_cast(window)); if (!surface->isValid()) { // there was a problem in the ctor, the error @@ -847,28 +948,28 @@ static EGLSurface createPixmapSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -900,10 +1001,10 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, EGLint surfaceType; if (getConfigAttrib(dpy, config, EGL_SURFACE_TYPE, &surfaceType) == EGL_FALSE) return EGL_FALSE; - + if (!(surfaceType & EGL_PBUFFER_BIT)) return setError(EGL_BAD_MATCH, EGL_NO_SURFACE); - + EGLint configID; if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE) return EGL_FALSE; @@ -911,28 +1012,28 @@ static EGLSurface createPbufferSurface(EGLDisplay dpy, EGLConfig config, int32_t depthFormat; int32_t pixelFormat; switch(configID) { - case 0: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + case 0: + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = 0; break; case 1: - pixelFormat = GGL_PIXEL_FORMAT_RGB_565; + pixelFormat = GGL_PIXEL_FORMAT_RGB_565; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 2: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = 0; break; case 3: - pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; + pixelFormat = GGL_PIXEL_FORMAT_RGBA_8888; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; case 4: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = 0; break; case 5: - pixelFormat = GGL_PIXEL_FORMAT_A_8; + pixelFormat = GGL_PIXEL_FORMAT_A_8; depthFormat = GGL_PIXEL_FORMAT_Z_16; break; default: @@ -985,7 +1086,7 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) egl_display_t& d = egl_display_t::get_display(dpy); d.type = display; return dpy; - } + } return EGL_NO_DISPLAY; } @@ -993,10 +1094,10 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - + EGLBoolean res = EGL_TRUE; egl_display_t& d = egl_display_t::get_display(dpy); - + if (android_atomic_inc(&d.initialized) == 0) { // initialize stuff here if needed //pthread_mutex_lock(&gInitMutex); @@ -1064,7 +1165,7 @@ EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, *num_config = 0; return EGL_TRUE; } - + int numAttributes = 0; int numConfigs = NELEM(gConfigs); uint32_t possibleMatch = (1<getSwapBehavior(); + *value = surface->getSwapBehavior(); break; default: ret = setError(EGL_BAD_ATTRIBUTE, EGL_FALSE); @@ -1278,7 +1379,7 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } EGLContext current_ctx = EGL_NO_CONTEXT; - + if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT)) return setError(EGL_BAD_MATCH, EGL_FALSE); @@ -1299,6 +1400,8 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, } } + // TODO: call connect / disconnect on the surface + ogles_context_t* gl = (ogles_context_t*)ctx; if (makeCurrent(gl) == 0) { if (ctx) { @@ -1407,7 +1510,7 @@ EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { if (egl_display_t::is_valid(dpy) == EGL_FALSE) return setError(EGL_BAD_DISPLAY, EGL_FALSE); - + egl_surface_t* d = static_cast(draw); if (d->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); @@ -1540,7 +1643,7 @@ EGLSurface eglCreatePbufferFromClientBuffer( } // ---------------------------------------------------------------------------- -// Android extensions +// EGL_EGLEXT_VERSION 3 // ---------------------------------------------------------------------------- void (*eglGetProcAddress (const char *procname))() @@ -1553,3 +1656,81 @@ void (*eglGetProcAddress (const char *procname))() } return NULL; } + +EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, + const EGLint *attrib_list) +{ + EGLBoolean result = EGL_FALSE; + return result; +} + +EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) +{ + EGLBoolean result = EGL_FALSE; + return result; +} + +EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attrib_list) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); + } + if (ctx != EGL_NO_CONTEXT) { + return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); + } + if (target != EGL_NATIVE_BUFFER_ANDROID) { + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)buffer; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + buffer_handle_t bufferHandle; + gralloc_module_t const* module = + reinterpret_cast(pModule); + if (native_buffer->getHandle(native_buffer, &bufferHandle) < 0) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + if (module->map(module, bufferHandle, &native_buffer->bits) < 0) + return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); + + native_buffer->common.incRef(&native_buffer->common); + return (EGLImageKHR)native_buffer; +} + +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) { + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + } + + android_native_buffer_t* native_buffer = (android_native_buffer_t*)img; + + if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + + if (native_buffer->common.version != sizeof(android_native_buffer_t)) + return setError(EGL_BAD_PARAMETER, EGL_FALSE); + + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule) == 0) { + buffer_handle_t bufferHandle; + gralloc_module_t const* module = + reinterpret_cast(pModule); + if (native_buffer->getHandle(native_buffer, &bufferHandle) == 0) { + module->unmap(module, bufferHandle); + } + } + + native_buffer->common.decRef(&native_buffer->common); + + return EGL_TRUE; +} -- cgit v1.2.3-59-g8ed1b From af9a515299b24031c7aa77bf163d0985cc862069 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Fri, 10 Apr 2009 20:34:46 -0700 Subject: more debugging tools around BufferMapper --- include/ui/BufferMapper.h | 14 ++++++ libs/surfaceflinger/BufferAllocator.cpp | 16 +++---- libs/surfaceflinger/LayerBitmap.h | 2 +- libs/ui/BufferMapper.cpp | 78 +++++++++++++++++++++++++++++++++ opengl/libagl/egl.cpp | 13 ++++-- 5 files changed, 110 insertions(+), 13 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/include/ui/BufferMapper.h b/include/ui/BufferMapper.h index 8a33b2eab9a5..9e5c5d7fd7fa 100644 --- a/include/ui/BufferMapper.h +++ b/include/ui/BufferMapper.h @@ -19,8 +19,11 @@ #include #include + +#include #include #include +#include #include @@ -42,11 +45,22 @@ public: status_t lock(buffer_handle_t handle, int usage, const Rect& bounds); status_t unlock(buffer_handle_t handle); + // dumps information about the mapping of this handle + void dump(buffer_handle_t handle); + private: friend class Singleton; BufferMapper(); mutable Mutex mLock; gralloc_module_t const *mAllocMod; + + struct map_info_t { + int count; + KeyedVector callstacks; + }; + KeyedVector mMapInfo; + void logMapLocked(buffer_handle_t handle); + void logUnmapLocked(buffer_handle_t handle); }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp index ac32985890ac..96a2c32f3832 100644 --- a/libs/surfaceflinger/BufferAllocator.cpp +++ b/libs/surfaceflinger/BufferAllocator.cpp @@ -104,11 +104,13 @@ status_t BufferAllocator::free(buffer_handle_t handle) { Mutex::Autolock _l(mLock); -#if ANDROID_GRALLOC_DEBUG - if (handle->data[2]) { - CallStack s; - s.update(); - s.dump(""); +#if ANDROID_GRALLOC_DEBUG + void* base = (void*)(handle->data[2]); + if (base) { + CallStack s; + s.update(); + s.dump(""); + BufferMapper::get().dump(handle); } #endif @@ -143,9 +145,7 @@ status_t BufferAllocator::unmap(buffer_handle_t handle) { Mutex::Autolock _l(mLock); gralloc_module_t* mod = (gralloc_module_t*)mAllocDev->common.module; - status_t err = mod->unmap(mod, handle); - LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); - + status_t err = BufferMapper::get().unmap(handle); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector& list(sAllocList); diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index d1f78021640e..e6737550f281 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -81,7 +81,7 @@ public: private: friend class LightRefBase; Buffer(const Buffer& rhs); - ~Buffer(); + virtual ~Buffer(); Buffer& operator = (const Buffer& rhs); const Buffer& operator = (const Buffer& rhs) const; diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp index a97188e73d85..c7e439c3c968 100644 --- a/libs/ui/BufferMapper.cpp +++ b/libs/ui/BufferMapper.cpp @@ -34,6 +34,13 @@ #include +// --------------------------------------------------------------------------- +// enable mapping debugging +#define DEBUG_MAPPINGS 1 +// never remove mappings from the list +#define DEBUG_MAPPINGS_KEEP_ALL 1 +// --------------------------------------------------------------------------- + namespace android { // --------------------------------------------------------------------------- @@ -53,6 +60,10 @@ status_t BufferMapper::map(buffer_handle_t handle, void** addr) Mutex::Autolock _l(mLock); status_t err = mAllocMod->map(mAllocMod, handle, addr); LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); +#if DEBUG_MAPPINGS + if (err == NO_ERROR) + logMapLocked(handle); +#endif return err; } @@ -61,6 +72,10 @@ status_t BufferMapper::unmap(buffer_handle_t handle) Mutex::Autolock _l(mLock); status_t err = mAllocMod->unmap(mAllocMod, handle); LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); +#if DEBUG_MAPPINGS + if (err == NO_ERROR) + logUnmapLocked(handle); +#endif return err; } @@ -79,5 +94,68 @@ status_t BufferMapper::unlock(buffer_handle_t handle) return err; } +void BufferMapper::logMapLocked(buffer_handle_t handle) +{ + CallStack stack; + stack.update(2); + + map_info_t info; + ssize_t index = mMapInfo.indexOfKey(handle); + if (index >= 0) { + info = mMapInfo.valueAt(index); + } + + ssize_t stackIndex = info.callstacks.indexOfKey(stack); + if (stackIndex >= 0) { + info.callstacks.editValueAt(stackIndex) += 1; + } else { + info.callstacks.add(stack, 1); + } + + if (index < 0) { + info.count = 1; + mMapInfo.add(handle, info); + } else { + info.count++; + mMapInfo.replaceValueAt(index, info); + } +} + +void BufferMapper::logUnmapLocked(buffer_handle_t handle) +{ + ssize_t index = mMapInfo.indexOfKey(handle); + if (index < 0) { + LOGE("unmapping %p which doesn't exist!", handle); + return; + } + + map_info_t& info = mMapInfo.editValueAt(index); + info.count--; + if (info.count == 0) { +#if DEBUG_MAPPINGS_KEEP_ALL + info.callstacks.clear(); +#else + mMapInfo.removeItemsAt(index, 1); +#endif + } +} + +void BufferMapper::dump(buffer_handle_t handle) +{ + Mutex::Autolock _l(mLock); + ssize_t index = mMapInfo.indexOfKey(handle); + if (index < 0) { + LOGD("handle %p is not mapped through BufferMapper", handle); + return; + } + + const map_info_t& info = mMapInfo.valueAt(index); + LOGD("dumping buffer_handle_t %p mappings (count=%d)", handle, info.count); + for (size_t i=0 ; i(pModule); if (native_buffer->getHandle(native_buffer, &bufferHandle) < 0) return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - if (module->map(module, bufferHandle, &native_buffer->bits) < 0) + int err = module->map(module, bufferHandle, &native_buffer->bits); + if (err < 0) { + LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - + } + native_buffer->common.incRef(&native_buffer->common); return (EGLImageKHR)native_buffer; } @@ -1725,8 +1728,10 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) buffer_handle_t bufferHandle; gralloc_module_t const* module = reinterpret_cast(pModule); - if (native_buffer->getHandle(native_buffer, &bufferHandle) == 0) { - module->unmap(module, bufferHandle); + int err = native_buffer->getHandle(native_buffer, &bufferHandle); + if (err == 0) { + int err = module->unmap(module, bufferHandle); + LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); } } -- cgit v1.2.3-59-g8ed1b From dff8e58d47ede6e748c0b02e128ca33b42a4f362 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 4 May 2009 14:17:04 -0700 Subject: update surfaceflinger, libui and libagl to the new gralloc api - Currently the lock/unlock path is naive and is done for each drawing operation (glDrawElements and glDrawArrays). this should be improved eventually. - factor all the lock/unlock code in SurfaceBuffer. - fixed "showupdate" so it works even when we don't have preserving eglSwapBuffers(). - improved the situation with the dirty-region and fixed a problem that caused GL apps to not update. - make use of LightRefBase() where needed, instead of duplicating its implementation - add LightRefBase::getStrongCount() - renamed EGLNativeWindowSurface.cpp to FramebufferNativeWindow.cpp - disabled copybits test, since it clashes with the new gralloc api - Camera/Video will be fixed later when we rework the overlay apis --- include/ui/BufferMapper.h | 23 +- include/ui/EGLDisplaySurface.h | 86 ------- include/ui/EGLNativeWindowSurface.h | 125 ---------- include/ui/FramebufferNativeWindow.h | 111 +++++++++ include/ui/Region.h | 1 + include/ui/Surface.h | 39 +-- include/utils/RefBase.h | 4 + libs/surfaceflinger/Android.mk | 3 - libs/surfaceflinger/BootAnimation.cpp | 2 +- libs/surfaceflinger/BufferAllocator.cpp | 56 +---- libs/surfaceflinger/BufferAllocator.h | 4 - .../DisplayHardware/DisplayHardware.cpp | 5 +- libs/surfaceflinger/Layer.cpp | 15 +- libs/surfaceflinger/LayerBase.cpp | 24 +- libs/surfaceflinger/LayerBase.h | 3 +- libs/surfaceflinger/LayerBitmap.cpp | 43 ++-- libs/surfaceflinger/LayerBitmap.h | 5 +- libs/surfaceflinger/LayerBuffer.cpp | 38 +-- libs/surfaceflinger/LayerOrientationAnim.cpp | 272 --------------------- libs/surfaceflinger/LayerOrientationAnim.h | 112 --------- libs/surfaceflinger/LayerOrientationAnimRotate.cpp | 269 -------------------- libs/surfaceflinger/LayerOrientationAnimRotate.h | 77 ------ libs/surfaceflinger/OrientationAnimation.cpp | 150 ------------ libs/surfaceflinger/OrientationAnimation.h | 84 ------- libs/surfaceflinger/SurfaceFlinger.cpp | 41 ++-- libs/surfaceflinger/SurfaceFlinger.h | 4 - .../purgatory/LayerOrientationAnim.cpp | 272 +++++++++++++++++++++ .../purgatory/LayerOrientationAnim.h | 112 +++++++++ .../purgatory/LayerOrientationAnimRotate.cpp | 269 ++++++++++++++++++++ .../purgatory/LayerOrientationAnimRotate.h | 77 ++++++ .../purgatory/OrientationAnimation.cpp | 150 ++++++++++++ .../purgatory/OrientationAnimation.h | 84 +++++++ libs/ui/Android.mk | 2 +- libs/ui/BufferMapper.cpp | 100 +------- libs/ui/EGLNativeWindowSurface.cpp | 244 ------------------ libs/ui/FramebufferNativeWindow.cpp | 214 ++++++++++++++++ libs/ui/Region.cpp | 7 + libs/ui/Surface.cpp | 225 ++++++++--------- opengl/include/EGL/android_natives.h | 26 +- opengl/libagl/TextureObjectManager.cpp | 20 +- opengl/libagl/TextureObjectManager.h | 50 +--- opengl/libagl/array.cpp | 17 ++ opengl/libagl/egl.cpp | 71 +++--- opengl/libagl/texture.cpp | 88 +++++-- opengl/libagl/texture.h | 10 +- opengl/tests/copybits/Android.mk | 2 +- 46 files changed, 1709 insertions(+), 1927 deletions(-) delete mode 100644 include/ui/EGLDisplaySurface.h delete mode 100644 include/ui/EGLNativeWindowSurface.h create mode 100644 include/ui/FramebufferNativeWindow.h delete mode 100644 libs/surfaceflinger/LayerOrientationAnim.cpp delete mode 100644 libs/surfaceflinger/LayerOrientationAnim.h delete mode 100644 libs/surfaceflinger/LayerOrientationAnimRotate.cpp delete mode 100644 libs/surfaceflinger/LayerOrientationAnimRotate.h delete mode 100644 libs/surfaceflinger/OrientationAnimation.cpp delete mode 100644 libs/surfaceflinger/OrientationAnimation.h create mode 100644 libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp create mode 100644 libs/surfaceflinger/purgatory/LayerOrientationAnim.h create mode 100644 libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp create mode 100644 libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h create mode 100644 libs/surfaceflinger/purgatory/OrientationAnimation.cpp create mode 100644 libs/surfaceflinger/purgatory/OrientationAnimation.h delete mode 100644 libs/ui/EGLNativeWindowSurface.cpp create mode 100644 libs/ui/FramebufferNativeWindow.cpp (limited to 'opengl/libagl/egl.cpp') diff --git a/include/ui/BufferMapper.h b/include/ui/BufferMapper.h index ff9003300296..5f084becf943 100644 --- a/include/ui/BufferMapper.h +++ b/include/ui/BufferMapper.h @@ -20,10 +20,7 @@ #include #include -#include -#include #include -#include #include @@ -40,9 +37,14 @@ class BufferMapper : public Singleton { public: static inline BufferMapper& get() { return getInstance(); } - status_t map(buffer_handle_t handle, void** addr, const void* id); - status_t unmap(buffer_handle_t handle, const void* id); - status_t lock(buffer_handle_t handle, int usage, const Rect& bounds); + + status_t registerBuffer(buffer_handle_t handle); + + status_t unregisterBuffer(buffer_handle_t handle); + + status_t lock(buffer_handle_t handle, + int usage, const Rect& bounds, void** vaddr); + status_t unlock(buffer_handle_t handle); // dumps information about the mapping of this handle @@ -51,16 +53,7 @@ public: private: friend class Singleton; BufferMapper(); - mutable Mutex mLock; gralloc_module_t const *mAllocMod; - - void logMapLocked(buffer_handle_t handle, const void* id); - void logUnmapLocked(buffer_handle_t handle, const void* id); - struct map_info_t { - const void* id; - CallStack stack; - }; - KeyedVector > mMapInfo; }; // --------------------------------------------------------------------------- diff --git a/include/ui/EGLDisplaySurface.h b/include/ui/EGLDisplaySurface.h deleted file mode 100644 index a8b58539d192..000000000000 --- a/include/ui/EGLDisplaySurface.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_EGL_DISPLAY_SURFACE_H -#define ANDROID_EGL_DISPLAY_SURFACE_H - -#include -#include - -#include - -#include - -#include -#include - -#include - -struct copybit_device_t; -struct copybit_image_t; - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class Region; -class Rect; - -class EGLDisplaySurface : public EGLNativeSurface -{ -public: - EGLDisplaySurface(); - ~EGLDisplaySurface(); - - int32_t getPageFlipCount() const; - void copyFrontToBack(const Region& copyback); - void copyFrontToImage(const copybit_image_t& dst); - void copyBackToImage(const copybit_image_t& dst); - - void setSwapRectangle(int l, int t, int w, int h); - -private: - static void hook_incRef(NativeWindowType window); - static void hook_decRef(NativeWindowType window); - static uint32_t hook_swapBuffers(NativeWindowType window); - - uint32_t swapBuffers(); - - status_t mapFrameBuffer(); - - enum { - PAGE_FLIP = 0x00000001 - }; - GGLSurface mFb[2]; - int mIndex; - uint32_t mFlags; - size_t mSize; - fb_var_screeninfo mInfo; - fb_fix_screeninfo mFinfo; - int32_t mPageFlipCount; - nsecs_t mTime; - int32_t mSwapCount; - nsecs_t mSleep; - uint32_t mFeatureFlags; - copybit_device_t* mBlitEngine; -}; - -// --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- - -#endif // ANDROID_EGL_DISPLAY_SURFACE_H - diff --git a/include/ui/EGLNativeWindowSurface.h b/include/ui/EGLNativeWindowSurface.h deleted file mode 100644 index 4b25655cf332..000000000000 --- a/include/ui/EGLNativeWindowSurface.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_EGL_NATIVE_WINDOW_SURFACE_H -#define ANDROID_EGL_NATIVE_WINDOW_SURFACE_H - -#include -#include - -#include -#include - -#include -#include - -#include - - -extern "C" EGLNativeWindowType android_createDisplaySurface(void); - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -class Surface; - - -class NativeBuffer - : public EGLNativeBase< - android_native_buffer_t, - NativeBuffer, - LightRefBase > -{ -public: - NativeBuffer(int w, int h, int f, int u) : BASE() { - android_native_buffer_t::width = w; - android_native_buffer_t::height = h; - android_native_buffer_t::format = f; - android_native_buffer_t::usage = u; - android_native_buffer_t::getHandle = getHandle; - } -public: - buffer_handle_t handle; -private: - friend class LightRefBase; - ~NativeBuffer() { }; // this class cannot be overloaded - static int getHandle(android_native_buffer_t const * base, buffer_handle_t* handle) { - *handle = getSelf(base)->handle; - return 0; - } -}; - -// --------------------------------------------------------------------------- - -class FramebufferNativeWindow - : public EGLNativeBase< - android_native_window_t, - FramebufferNativeWindow, - LightRefBase > -{ -public: - FramebufferNativeWindow(); - - framebuffer_device_t const * getDevice() const { return fbDev; } - -private: - friend class LightRefBase; - ~FramebufferNativeWindow(); // this class cannot be overloaded - static void connect(android_native_window_t* window); - static void disconnect(android_native_window_t* window); - static int setSwapInterval(android_native_window_t* window, int interval); - static int setSwapRectangle(android_native_window_t* window, - int l, int t, int w, int h); - static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); - static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); - static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); - - - static inline FramebufferNativeWindow* getSelf( - android_native_window_t* window) { - FramebufferNativeWindow* self = - static_cast(window); - return self; - } - - static inline FramebufferNativeWindow* getSelf( - android_native_base_t* window) { - return getSelf(reinterpret_cast(window)); - } - - - framebuffer_device_t* fbDev; - alloc_device_t* grDev; - - sp buffers[2]; - sp front; - - Rect mDirty; - - mutable Mutex mutex; - Condition mCondition; - int32_t mNumBuffers; - int32_t mNumFreeBuffers; - int32_t mBufferHead; -}; - -// --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- - -#endif // ANDROID_EGL_NATIVE_WINDOW_SURFACE_H - diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h new file mode 100644 index 000000000000..1d49cca401ae --- /dev/null +++ b/include/ui/FramebufferNativeWindow.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H +#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H + +#include +#include + +#include +#include + +#include +#include + +#include + + +extern "C" EGLNativeWindowType android_createDisplaySurface(void); + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class Surface; + + +class NativeBuffer + : public EGLNativeBase< + android_native_buffer_t, + NativeBuffer, + LightRefBase > +{ +public: + NativeBuffer(int w, int h, int f, int u) : BASE() { + android_native_buffer_t::width = w; + android_native_buffer_t::height = h; + android_native_buffer_t::format = f; + android_native_buffer_t::usage = u; + android_native_buffer_t::getHandle = getHandle; + } +public: + buffer_handle_t handle; +private: + friend class LightRefBase; + ~NativeBuffer() { }; // this class cannot be overloaded + static int getHandle(android_native_buffer_t const * base, buffer_handle_t* handle) { + *handle = getSelf(base)->handle; + return 0; + } +}; + +// --------------------------------------------------------------------------- + +class FramebufferNativeWindow + : public EGLNativeBase< + android_native_window_t, + FramebufferNativeWindow, + LightRefBase > +{ +public: + FramebufferNativeWindow(); + + framebuffer_device_t const * getDevice() const { return fbDev; } + + void setSwapRectangle(const Rect& dirty); + +private: + friend class LightRefBase; + ~FramebufferNativeWindow(); // this class cannot be overloaded + static void connect(android_native_window_t* window); + static void disconnect(android_native_window_t* window); + static int setSwapInterval(android_native_window_t* window, int interval); + static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); + static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); + + framebuffer_device_t* fbDev; + alloc_device_t* grDev; + + sp buffers[2]; + sp front; + + Rect mDirty; + + mutable Mutex mutex; + Condition mCondition; + int32_t mNumBuffers; + int32_t mNumFreeBuffers; + int32_t mBufferHead; +}; + +// --------------------------------------------------------------------------- +}; // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H + diff --git a/include/ui/Region.h b/include/ui/Region.h index 76896737f293..5efeff7d32ad 100644 --- a/include/ui/Region.h +++ b/include/ui/Region.h @@ -57,6 +57,7 @@ public: void clear(); void set(const Rect& r); + void set(uint32_t w, uint32_t h); Region& orSelf(const Rect& rhs); Region& andSelf(const Rect& rhs); diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 16d2edb8e223..6eb06ae65f35 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -34,7 +34,9 @@ namespace android { // --------------------------------------------------------------------------- +class BufferMapper; class Rect; +class Surface; class SurfaceComposerClient; struct per_client_cblk_t; struct layer_cblk_t; @@ -52,6 +54,10 @@ public: return handle; } + status_t lock(uint32_t usage); + status_t lock(uint32_t usage, const Rect& rect); + status_t unlock(); + protected: SurfaceBuffer(); SurfaceBuffer(const Parcel& reply); @@ -59,7 +65,11 @@ protected: buffer_handle_t handle; bool mOwner; + inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } + inline BufferMapper& getBufferMapper() { return mBufferMapper; } + private: + friend class Surface; friend class BpSurface; friend class BnSurface; friend class LightRefBase; @@ -72,6 +82,8 @@ private: static int getHandle(android_native_buffer_t const * base, buffer_handle_t* handle); + + BufferMapper& mBufferMapper; }; // --------------------------------------------------------------------------- @@ -191,9 +203,8 @@ public: status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true); status_t unlockAndPost(); - // setSwapRectangle() is mainly used by EGL + // setSwapRectangle() is intended to be used by GL ES clients void setSwapRectangle(const Rect& r); - const Rect& swapRectangle() const; private: // can't be copied @@ -216,22 +227,14 @@ private: const sp& getISurface() const { return mSurface; } status_t getBufferLocked(int index); - - - - Region dirtyRegion() const; - void setDirtyRegion(const Region& region) const; - status_t validate(per_client_cblk_t const* cblk) const; static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty); + inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } + inline BufferMapper& getBufferMapper() { return mBufferMapper; } - static void connect(android_native_window_t* window); - static void disconnect(android_native_window_t* window); static int setSwapInterval(android_native_window_t* window, int interval); - static int setSwapRectangle(android_native_window_t* window, - int l, int t, int w, int h); static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer); @@ -239,21 +242,27 @@ private: int dequeueBuffer(android_native_buffer_t** buffer); int lockBuffer(android_native_buffer_t* buffer); int queueBuffer(android_native_buffer_t* buffer); - + + status_t dequeueBuffer(sp* buffer); + status_t lockBuffer(const sp& buffer); + status_t queueBuffer(const sp& buffer); + alloc_device_t* mAllocDevice; sp mClient; sp mSurface; sp mBuffers[2]; - android_native_buffer_t* mLockedBuffer; + sp mLockedBuffer; SurfaceID mToken; uint32_t mIdentity; PixelFormat mFormat; uint32_t mFlags; mutable Region mDirtyRegion; - mutable Rect mSwapRectangle; + mutable Region mOldDirtyRegion; mutable uint8_t mBackbufferIndex; mutable Mutex mSurfaceLock; + Rect mSwapRectangle; + BufferMapper& mBufferMapper; }; }; // namespace android diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index cbda0fd80db6..bd7f28cae3a1 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -156,6 +156,10 @@ public: delete static_cast(this); } } + //! DEBUGGING ONLY: Get current strong ref count. + inline int32_t getStrongCount() const { + return mCount; + } protected: inline ~LightRefBase() { } diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index 2b360d620595..639a82eaeb97 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -14,10 +14,7 @@ LOCAL_SRC_FILES:= \ LayerBlur.cpp \ LayerBitmap.cpp \ LayerDim.cpp \ - LayerOrientationAnim.cpp \ - LayerOrientationAnimRotate.cpp \ MessageQueue.cpp \ - OrientationAnimation.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ Transform.cpp diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp index ee36b6703a39..b45fe3489a9e 100644 --- a/libs/surfaceflinger/BootAnimation.cpp +++ b/libs/surfaceflinger/BootAnimation.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include diff --git a/libs/surfaceflinger/BufferAllocator.cpp b/libs/surfaceflinger/BufferAllocator.cpp index fec7c8770584..cee8b643dde6 100644 --- a/libs/surfaceflinger/BufferAllocator.cpp +++ b/libs/surfaceflinger/BufferAllocator.cpp @@ -16,20 +16,14 @@ */ #include -#include #include #include #include #include -#include - #include "BufferAllocator.h" -// FIXME: ANDROID_GRALLOC_DEBUG must only be used with *our* gralloc -#define ANDROID_GRALLOC_DEBUG 1 - namespace android { // --------------------------------------------------------------------------- @@ -67,8 +61,8 @@ void BufferAllocator::dump(String8& result) const const size_t c = list.size(); for (size_t i=0 ; idata[2]); -#endif - status_t err = mAllocDev->free(mAllocDev, handle); LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); -#if ANDROID_GRALLOC_DEBUG - if (base) { - LOGD("freeing mapped handle %p from:", handle); - CallStack s; - s.update(); - s.dump(""); - BufferMapper::get().dump(handle); - } -#endif - if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector& list(sAllocList); @@ -134,37 +114,5 @@ status_t BufferAllocator::free(buffer_handle_t handle) return err; } -status_t BufferAllocator::map(buffer_handle_t handle, void** addr) -{ - Mutex::Autolock _l(mLock); - status_t err = BufferMapper::get().map(handle, addr, this); - if (err == NO_ERROR) { - Mutex::Autolock _l(sLock); - KeyedVector& list(sAllocList); - ssize_t idx = list.indexOfKey(handle); - if (idx >= 0) - list.editValueAt(idx).vaddr = addr; - } - - return err; -} - -status_t BufferAllocator::unmap(buffer_handle_t handle) -{ - Mutex::Autolock _l(mLock); - gralloc_module_t* mod = (gralloc_module_t*)mAllocDev->common.module; - status_t err = BufferMapper::get().unmap(handle, this); - if (err == NO_ERROR) { - Mutex::Autolock _l(sLock); - KeyedVector& list(sAllocList); - ssize_t idx = list.indexOfKey(handle); - if (idx >= 0) - list.editValueAt(idx).vaddr = 0; - } - - return err; -} - - // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/surfaceflinger/BufferAllocator.h b/libs/surfaceflinger/BufferAllocator.h index 0b69b8ecd46f..a279deda941c 100644 --- a/libs/surfaceflinger/BufferAllocator.h +++ b/libs/surfaceflinger/BufferAllocator.h @@ -67,10 +67,6 @@ public: status_t free(buffer_handle_t handle); - status_t map(buffer_handle_t handle, void** addr); - - status_t unmap(buffer_handle_t handle); - void dump(String8& res) const; private: diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 1f7211cc13ca..83ebd7a617d3 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -313,8 +313,7 @@ void DisplayHardware::flip(const Region& dirty) const } const Rect& b(newDirty.bounds()); - mNativeWindow->android_native_window_t::setSwapRectangle( - mNativeWindow.get(), b.left, b.top, b.width(), b.height()); + mNativeWindow->setSwapRectangle(b); mPageFlipCount++; eglSwapBuffers(dpy, surface); diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 8a7d46784f55..76259317482f 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -69,8 +69,6 @@ void Layer::destroy() { for (int i=0 ; i& buffer(frontBuffer().getBuffer()); - if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { + const sp& buffer(frontBuffer().getBuffer()); + if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { int index = mFrontBufferIndex; if (LIKELY(!mTextures[index].dirty)) { glBindTexture(GL_TEXTURE_2D, mTextures[index].name); @@ -197,12 +195,16 @@ void Layer::reloadTexture(const Region& dirty) } } else { GGLSurface t; - if (LIKELY(buffer->getBitmapSurface(&t) == NO_ERROR)) { + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + LOGE_IF(res, "error %d (%s) locking buffer %p", + res, strerror(res), buffer.get()); + if (res == NO_ERROR) { if (UNLIKELY(mTextures[0].name == -1U)) { mTextures[0].name = createTexture(); } loadTexture(dirty, mTextures[0].name, t, mTextures[0].width, mTextures[0].height); + buffer->unlock(); } } } @@ -225,8 +227,7 @@ void Layer::onDraw(const Region& clip) const GGLSurface t; sp buffer(frontBuffer().getBuffer()); - buffer->getBitmapSurface(&t); - drawWithOpenGL(clip, textureName, t); + drawWithOpenGL(clip, textureName, buffer); } sp Layer::peekBuffer() diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index ef5a9598d69e..cc9c586b421a 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -377,12 +377,14 @@ void LayerBase::clearWithOpenGL(const Region& clip) const } void LayerBase::drawWithOpenGL(const Region& clip, - GLint textureName, const GGLSurface& t, int transform) const + GLint textureName, const sp& buffer, int transform) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); const State& s(drawingState()); - + const uint32_t width = buffer->width; + const uint32_t height = buffer->height; + // bind our texture validateTexture(textureName); glEnable(GL_TEXTURE_2D); @@ -457,14 +459,14 @@ void LayerBase::drawWithOpenGL(const Region& clip, if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { // find the smallest power-of-two that will accommodate our surface - GLuint tw = 1 << (31 - clz(t.width)); - GLuint th = 1 << (31 - clz(t.height)); - if (tw < t.width) tw <<= 1; - if (th < t.height) th <<= 1; + GLuint tw = 1 << (31 - clz(width)); + GLuint th = 1 << (31 - clz(height)); + if (tw < width) tw <<= 1; + if (th < height) th <<= 1; // this divide should be relatively fast because it's // a power-of-two (optimized path in libgcc) - GLfloat ws = GLfloat(t.width) /tw; - GLfloat hs = GLfloat(t.height)/th; + GLfloat ws = GLfloat(width) /tw; + GLfloat hs = GLfloat(height)/th; glScalef(ws, hs, 1.0f); } @@ -489,15 +491,15 @@ void LayerBase::drawWithOpenGL(const Region& clip, Region::iterator iterator(clip); if (iterator) { Rect r; - GLint crop[4] = { 0, t.height, t.width, -t.height }; + GLint crop[4] = { 0, height, width, -height }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); int x = tx(); int y = ty(); - y = fbHeight - (y + t.height); + y = fbHeight - (y + height); while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); glScissor(r.left, sy, r.width(), r.height()); - glDrawTexiOES(x, y, 0, t.width, t.height); + glDrawTexiOES(x, y, 0, width, height); } } } diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index c177c2a4faf2..509dedd743f1 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -40,6 +40,7 @@ class DisplayHardware; class GraphicPlane; class Client; class SurfaceBuffer; +class Buffer; // --------------------------------------------------------------------------- @@ -239,7 +240,7 @@ protected: void drawWithOpenGL(const Region& clip, GLint textureName, - const GGLSurface& surface, + const sp& buffer, int transform = 0) const; void clearWithOpenGL(const Region& clip) const; diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index d633a2d52bf4..38d4bcf02f7d 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -52,10 +52,7 @@ Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) Buffer::~Buffer() { if (handle) { - BufferAllocator& allocator = BufferAllocator::get(); - if (usage & BufferAllocator::USAGE_SW_READ_MASK) { - allocator.unmap(handle); - } + BufferAllocator& allocator(BufferAllocator::get()); allocator.free(handle); } } @@ -107,9 +104,6 @@ status_t Buffer::initSize(uint32_t w, uint32_t h) err = allocator.alloc(w, h, format, usage, &handle, &stride); if (err == NO_ERROR) { - if (usage & BufferAllocator::USAGE_SW_READ_MASK) { - err = allocator.map(handle, &bits); - } if (err == NO_ERROR) { width = w; height = h; @@ -120,31 +114,22 @@ status_t Buffer::initSize(uint32_t w, uint32_t h) return err; } -status_t Buffer::getBitmapSurface(copybit_image_t* img) const +status_t Buffer::lock(GGLSurface* sur, uint32_t usage) { - img->w = stride ?: width; - img->h = mVStride ?: height; - img->format = format; - - // FIXME: this should use a native_handle - img->offset = 0; - img->base = bits; - img->fd = getHandle()->data[0]; - - return NO_ERROR; + status_t res = SurfaceBuffer::lock(usage); + if (res == NO_ERROR && sur) { + sur->version = sizeof(GGLSurface); + sur->width = width; + sur->height = height; + sur->stride = stride; + sur->format = format; + sur->vstride = mVStride; + sur->data = static_cast(bits); + } + return res; } -status_t Buffer::getBitmapSurface(GGLSurface* sur) const -{ - sur->version = sizeof(GGLSurface); - sur->width = width; - sur->height = height; - sur->stride = stride; - sur->format = format; - sur->vstride = mVStride; - sur->data = static_cast(bits); - return NO_ERROR; -} + // =========================================================================== // LayerBitmap diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index e6737550f281..6e136a2ae764 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -73,9 +73,8 @@ public: PixelFormat getPixelFormat() const { return format; } Rect getBounds() const { return Rect(width, height); } - status_t getBitmapSurface(copybit_image_t* img) const; - status_t getBitmapSurface(GGLSurface* surface) const; - + status_t lock(GGLSurface* surface, uint32_t usage); + android_native_buffer_t* getNativeBuffer() const; private: diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index 9339b8758cc1..8be91c9febf1 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -380,37 +380,37 @@ bool LayerBuffer::BufferSource::transformed() const void LayerBuffer::BufferSource::onDraw(const Region& clip) const { - sp buffer(getBuffer()); + // FIXME: we should get a native buffer here + /* + sp ourBbuffer(getBuffer()); if (UNLIKELY(buffer == 0)) { // nothing to do, we don't have a buffer mLayer.clearWithOpenGL(clip); return; } - status_t err = NO_ERROR; - NativeBuffer src(buffer->getBuffer()); - const Rect& transformedBounds = mLayer.getTransformedBounds(); - // FIXME: We should model this after the overlay stuff - if (UNLIKELY(mTextureName == -1LU)) { mTextureName = mLayer.createTexture(); } - GLuint w = 0; - GLuint h = 0; - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.crop.r; - t.height = src.crop.b; - 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); - const Region dirty(Rect(t.width, t.height)); // FIXME: Use EGLImage extension for this - mLayer.loadTexture(dirty, mTextureName, t, w, h); - mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); + + + + GGLSurface t; + status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_RARELY); + if (res == NO_ERROR) { + GLuint w = 0; + GLuint h = 0; + const Region dirty(Rect(buffer->width, buffer->height)); + mLayer.loadTexture(dirty, mTextureName, t, w, h); + buffer->unlock(); + } + if (res == NO_ERROR) { + mLayer.drawWithOpenGL(clip, mTextureName, buffer, mBufferHeap.transform); + } + */ } diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp deleted file mode 100644 index 41c42d177573..000000000000 --- a/libs/surfaceflinger/LayerOrientationAnim.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include -#include -#include - -#include -#include -#include - -#include "BlurFilter.h" -#include "LayerBase.h" -#include "LayerOrientationAnim.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" -#include "OrientationAnimation.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80; -const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; - -// --------------------------------------------------------------------------- - -// Animation... -const float DURATION = ms2ns(200); -const float BOUNCES_PER_SECOND = 0.5f; -//const float BOUNCES_AMPLITUDE = 1.0f/16.0f; -const float BOUNCES_AMPLITUDE = 0; -const float DIM_TARGET = 0.40f; -//#define INTERPOLATED_TIME(_t) ((_t)*(_t)) -#define INTERPOLATED_TIME(_t) (_t) - -// --------------------------------------------------------------------------- - -LayerOrientationAnim::LayerOrientationAnim( - SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const sp& bitmapIn, - const sp& bitmapOut) - : LayerOrientationAnimBase(flinger, display), mAnim(anim), - mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), - mTextureName(-1), mTextureNameIn(-1) -{ - // blur that texture. - mStartTime = systemTime(); - mFinishTime = 0; - mOrientationCompleted = false; - mFirstRedraw = false; - mLastNormalizedTime = 0; - mNeedsBlending = false; - mAlphaInLerp.set(1.0f, DIM_TARGET); - mAlphaOutLerp.set(0.5f, 1.0f); -} - -LayerOrientationAnim::~LayerOrientationAnim() -{ - if (mTextureName != -1U) { - glDeleteTextures(1, &mTextureName); - } - if (mTextureNameIn != -1U) { - glDeleteTextures(1, &mTextureNameIn); - } -} - -bool LayerOrientationAnim::needsBlending() const -{ - return mNeedsBlending; -} - -Point LayerOrientationAnim::getPhysicalSize() const -{ - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - return Point(hw.getWidth(), hw.getHeight()); -} - -void LayerOrientationAnim::validateVisibility(const Transform&) -{ - const Layer::State& s(drawingState()); - const Transform tr(s.transform); - const Point size(getPhysicalSize()); - uint32_t w = size.x; - uint32_t h = size.y; - mTransformedBounds = tr.makeBounds(w, h); - mLeft = tr.tx(); - mTop = tr.ty(); - transparentRegionScreen.clear(); - mTransformed = true; -} - -void LayerOrientationAnim::onOrientationCompleted() -{ - mFinishTime = systemTime(); - mOrientationCompleted = true; - mFirstRedraw = true; - mNeedsBlending = true; - mFlinger->invalidateLayerVisibility(this); -} - -void LayerOrientationAnim::onDraw(const Region& clip) const -{ - const nsecs_t now = systemTime(); - float alphaIn, alphaOut; - - if (mOrientationCompleted) { - if (mFirstRedraw) { - mFirstRedraw = false; - - // make a copy of what's on screen - copybit_image_t image; - mBitmapOut->getBitmapSurface(&image); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.copyBackToImage(image); - - // and erase the screen for this round - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - - // FIXME: code below is gross - mNeedsBlending = false; - LayerOrientationAnim* self(const_cast(this)); - mFlinger->invalidateLayerVisibility(self); - } - - // make sure pick-up where we left off - const float duration = DURATION * mLastNormalizedTime; - const float normalizedTime = (float(now - mFinishTime) / duration); - if (normalizedTime <= 1.0f) { - const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); - alphaIn = mAlphaInLerp.getOut(); - alphaOut = mAlphaOutLerp(interpolatedTime); - } else { - mAnim->onAnimationFinished(); - alphaIn = mAlphaInLerp.getOut(); - alphaOut = mAlphaOutLerp.getOut(); - } - } else { - const float normalizedTime = float(now - mStartTime) / DURATION; - if (normalizedTime <= 1.0f) { - mLastNormalizedTime = normalizedTime; - const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); - alphaIn = mAlphaInLerp(interpolatedTime); - alphaOut = 0.0f; - } else { - mLastNormalizedTime = 1.0f; - const float to_seconds = DURATION / seconds(1); - alphaIn = mAlphaInLerp.getOut(); - if (BOUNCES_AMPLITUDE > 0.0f) { - const float phi = BOUNCES_PER_SECOND * - (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); - if (alphaIn > 1.0f) alphaIn = 1.0f; - else if (alphaIn < 0.0f) alphaIn = 0.0f; - alphaIn += BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); - } - alphaOut = 0.0f; - } - mAlphaOutLerp.setIn(alphaIn); - } - drawScaled(1.0f, alphaIn, alphaOut); -} - -void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut) const -{ - copybit_image_t dst; - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - //hw.getDisplaySurface(&dst); - - // clear screen - // TODO: with update on demand, we may be able - // to not erase the screen at all during the animation - if (!mOrientationCompleted) { - if (scale==1.0f && (alphaIn>=1.0f || alphaOut>=1.0f)) { - // we don't need to erase the screen in that case - } else { - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - } - } - - copybit_image_t src; - mBitmapIn->getBitmapSurface(&src); - - copybit_image_t srcOut; - mBitmapOut->getBitmapSurface(&srcOut); - - const int w = dst.w*scale; - const int h = dst.h*scale; - const int xc = uint32_t(dst.w-w)/2; - const int yc = uint32_t(dst.h-h)/2; - const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; - const copybit_rect_t srect = { 0, 0, src.w, src.h }; - const Region reg(Rect( drect.l, drect.t, drect.r, drect.b )); - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.w; - t.height = src.h; - t.stride = src.w; - t.vstride= src.h; - t.format = src.format; - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - - Transform tr; - tr.set(scale,0,0,scale); - tr.set(xc, yc); - - // FIXME: we should not access mVertices and mDrawingState like that, - // but since we control the animation, we know it's going to work okay. - // eventually we'd need a more formal way of doing things like this. - LayerOrientationAnim& self(const_cast(*this)); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // Too slow to do this in software - self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; - } - - if (alphaIn > 0.0f) { - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureNameIn == -1LU)) { - mTextureNameIn = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureNameIn, t, w, h); - } - self.mDrawingState.alpha = int(alphaIn*255); - drawWithOpenGL(reg, mTextureNameIn, t); - } - - if (alphaOut > 0.0f) { - t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = int(alphaOut*255); - drawWithOpenGL(reg, mTextureName, t); - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerOrientationAnim.h b/libs/surfaceflinger/LayerOrientationAnim.h deleted file mode 100644 index 472c45a1afef..000000000000 --- a/libs/surfaceflinger/LayerOrientationAnim.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_LAYER_ORIENTATION_ANIM_H -#define ANDROID_LAYER_ORIENTATION_ANIM_H - -#include -#include -#include -#include - -#include "LayerBase.h" -#include "LayerBitmap.h" - -namespace android { - -// --------------------------------------------------------------------------- -class OrientationAnimation; - - -class LayerOrientationAnimBase : public LayerBase -{ -public: - LayerOrientationAnimBase(SurfaceFlinger* flinger, DisplayID display) - : LayerBase(flinger, display) { - } - virtual void onOrientationCompleted() = 0; -}; - -// --------------------------------------------------------------------------- - -class LayerOrientationAnim : public LayerOrientationAnimBase -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const sp& bitmapIn, - const sp& bitmapOut); - virtual ~LayerOrientationAnim(); - - void onOrientationCompleted(); - - virtual void onDraw(const Region& clip) const; - virtual Point getPhysicalSize() const; - virtual void validateVisibility(const Transform& globalTransform); - virtual bool needsBlending() const; - virtual bool isSecure() const { return false; } -private: - void drawScaled(float scale, float alphaIn, float alphaOut) const; - - class Lerp { - float in; - float outMinusIn; - public: - Lerp() : in(0), outMinusIn(0) { } - Lerp(float in, float out) : in(in), outMinusIn(out-in) { } - float getIn() const { return in; }; - float getOut() const { return in + outMinusIn; } - void set(float in, float out) { - this->in = in; - this->outMinusIn = out-in; - } - void setIn(float in) { - this->in = in; - } - void setOut(float out) { - this->outMinusIn = out - this->in; - } - float operator()(float t) const { - return outMinusIn*t + in; - } - }; - - OrientationAnimation* mAnim; - sp mBitmapIn; - sp mBitmapOut; - nsecs_t mStartTime; - nsecs_t mFinishTime; - bool mOrientationCompleted; - mutable bool mFirstRedraw; - mutable float mLastNormalizedTime; - mutable GLuint mTextureName; - mutable GLuint mTextureNameIn; - mutable bool mNeedsBlending; - - mutable Lerp mAlphaInLerp; - mutable Lerp mAlphaOutLerp; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_ORIENTATION_ANIM_H diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/LayerOrientationAnimRotate.cpp deleted file mode 100644 index dc6b632a694d..000000000000 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#define LOG_TAG "SurfaceFlinger" - -#include -#include -#include - -#include -#include - -#include "LayerBase.h" -#include "LayerOrientationAnim.h" -#include "LayerOrientationAnimRotate.h" -#include "SurfaceFlinger.h" -#include "DisplayHardware/DisplayHardware.h" -#include "OrientationAnimation.h" - -namespace android { -// --------------------------------------------------------------------------- - -const uint32_t LayerOrientationAnimRotate::typeInfo = LayerBase::typeInfo | 0x100; -const char* const LayerOrientationAnimRotate::typeID = "LayerOrientationAnimRotate"; - -// --------------------------------------------------------------------------- - -const float ROTATION = M_PI * 0.5f; -const float ROTATION_FACTOR = 1.0f; // 1.0 or 2.0 -const float DURATION = ms2ns(200); -const float BOUNCES_PER_SECOND = 0.8; -const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; - -LayerOrientationAnimRotate::LayerOrientationAnimRotate( - SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const sp& bitmapIn, - const sp& bitmapOut) - : LayerOrientationAnimBase(flinger, display), mAnim(anim), - mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), - mTextureName(-1), mTextureNameIn(-1) -{ - mStartTime = systemTime(); - mFinishTime = 0; - mOrientationCompleted = false; - mFirstRedraw = false; - mLastNormalizedTime = 0; - mLastAngle = 0; - mLastScale = 0; - mNeedsBlending = false; - const GraphicPlane& plane(graphicPlane(0)); - mOriginalTargetOrientation = plane.getOrientation(); -} - -LayerOrientationAnimRotate::~LayerOrientationAnimRotate() -{ - if (mTextureName != -1U) { - glDeleteTextures(1, &mTextureName); - } - if (mTextureNameIn != -1U) { - glDeleteTextures(1, &mTextureNameIn); - } -} - -bool LayerOrientationAnimRotate::needsBlending() const -{ - return mNeedsBlending; -} - -Point LayerOrientationAnimRotate::getPhysicalSize() const -{ - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - return Point(hw.getWidth(), hw.getHeight()); -} - -void LayerOrientationAnimRotate::validateVisibility(const Transform&) -{ - const Layer::State& s(drawingState()); - const Transform tr(s.transform); - const Point size(getPhysicalSize()); - uint32_t w = size.x; - uint32_t h = size.y; - mTransformedBounds = tr.makeBounds(w, h); - mLeft = tr.tx(); - mTop = tr.ty(); - transparentRegionScreen.clear(); - mTransformed = true; -} - -void LayerOrientationAnimRotate::onOrientationCompleted() -{ - mFinishTime = systemTime(); - mOrientationCompleted = true; - mFirstRedraw = true; - mNeedsBlending = true; - mFlinger->invalidateLayerVisibility(this); -} - -void LayerOrientationAnimRotate::onDraw(const Region& clip) const -{ - // Animation... - - const nsecs_t now = systemTime(); - float angle, scale, alpha; - - if (mOrientationCompleted) { - if (mFirstRedraw) { - // make a copy of what's on screen - copybit_image_t image; - mBitmapIn->getBitmapSurface(&image); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.copyBackToImage(image); - - // FIXME: code below is gross - mFirstRedraw = false; - mNeedsBlending = false; - LayerOrientationAnimRotate* self(const_cast(this)); - mFlinger->invalidateLayerVisibility(self); - } - - // make sure pick-up where we left off - const float duration = DURATION * mLastNormalizedTime; - const float normalizedTime = (float(now - mFinishTime) / duration); - if (normalizedTime <= 1.0f) { - const float squaredTime = normalizedTime*normalizedTime; - angle = (ROTATION*ROTATION_FACTOR - mLastAngle)*squaredTime + mLastAngle; - scale = (1.0f - mLastScale)*squaredTime + mLastScale; - alpha = normalizedTime; - } else { - mAnim->onAnimationFinished(); - angle = ROTATION; - alpha = 1.0f; - scale = 1.0f; - } - } else { - // FIXME: works only for portrait framebuffers - const Point size(getPhysicalSize()); - const float TARGET_SCALE = size.x * (1.0f / size.y); - const float normalizedTime = float(now - mStartTime) / DURATION; - if (normalizedTime <= 1.0f) { - mLastNormalizedTime = normalizedTime; - const float squaredTime = normalizedTime*normalizedTime; - angle = ROTATION * squaredTime; - scale = (TARGET_SCALE - 1.0f)*squaredTime + 1.0f; - alpha = 0; - } else { - mLastNormalizedTime = 1.0f; - angle = ROTATION; - if (BOUNCES_AMPLITUDE) { - const float to_seconds = DURATION / seconds(1); - const float phi = BOUNCES_PER_SECOND * - (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); - angle += BOUNCES_AMPLITUDE * sinf(phi); - } - scale = TARGET_SCALE; - alpha = 0; - } - mLastAngle = angle; - mLastScale = scale; - } - drawScaled(angle, scale, alpha); -} - -void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const -{ - copybit_image_t dst; - const GraphicPlane& plane(graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - //hw.getDisplaySurface(&dst); - - // clear screen - // TODO: with update on demand, we may be able - // to not erase the screen at all during the animation - glDisable(GL_BLEND); - glDisable(GL_DITHER); - glDisable(GL_SCISSOR_TEST); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT); - - const int w = dst.w; - const int h = dst.h; - - copybit_image_t src; - mBitmapIn->getBitmapSurface(&src); - const copybit_rect_t srect = { 0, 0, src.w, src.h }; - - - GGLSurface t; - t.version = sizeof(GGLSurface); - t.width = src.w; - t.height = src.h; - t.stride = src.w; - t.vstride= src.h; - t.format = src.format; - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - - if (!mOriginalTargetOrientation) { - f = -f; - } - - Transform tr; - tr.set(f, w*0.5f, h*0.5f); - tr.scale(s, w*0.5f, h*0.5f); - - // FIXME: we should not access mVertices and mDrawingState like that, - // but since we control the animation, we know it's going to work okay. - // eventually we'd need a more formal way of doing things like this. - LayerOrientationAnimRotate& self(const_cast(*this)); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - - if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { - // Too slow to do this in software - self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; - } - - if (UNLIKELY(mTextureName == -1LU)) { - mTextureName = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureName, t, w, h); - } - self.mDrawingState.alpha = 255; //-int(alpha*255); - const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); - drawWithOpenGL(clip, mTextureName, t); - - if (alpha > 0) { - const float sign = (!mOriginalTargetOrientation) ? 1.0f : -1.0f; - tr.set(f + sign*(M_PI * 0.5f * ROTATION_FACTOR), w*0.5f, h*0.5f); - tr.scale(s, w*0.5f, h*0.5f); - tr.transform(self.mVertices[0], 0, 0); - tr.transform(self.mVertices[1], 0, src.h); - tr.transform(self.mVertices[2], src.w, src.h); - tr.transform(self.mVertices[3], src.w, 0); - - copybit_image_t src; - mBitmapIn->getBitmapSurface(&src); - t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); - if (UNLIKELY(mTextureNameIn == -1LU)) { - mTextureNameIn = createTexture(); - GLuint w=0, h=0; - const Region dirty(Rect(t.width, t.height)); - loadTexture(dirty, mTextureNameIn, t, w, h); - } - self.mDrawingState.alpha = int(alpha*255); - const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); - drawWithOpenGL(clip, mTextureNameIn, t); - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/LayerOrientationAnimRotate.h b/libs/surfaceflinger/LayerOrientationAnimRotate.h deleted file mode 100644 index a675c79b5176..000000000000 --- a/libs/surfaceflinger/LayerOrientationAnimRotate.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H -#define ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H - -#include -#include -#include -#include - -#include "LayerBase.h" -#include "LayerBitmap.h" - -namespace android { - -// --------------------------------------------------------------------------- -class OrientationAnimation; - -class LayerOrientationAnimRotate : public LayerOrientationAnimBase -{ -public: - static const uint32_t typeInfo; - static const char* const typeID; - virtual char const* getTypeID() const { return typeID; } - virtual uint32_t getTypeInfo() const { return typeInfo; } - - LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, - OrientationAnimation* anim, - const sp& bitmapIn, - const sp& bitmapOut); - virtual ~LayerOrientationAnimRotate(); - - void onOrientationCompleted(); - - virtual void onDraw(const Region& clip) const; - virtual Point getPhysicalSize() const; - virtual void validateVisibility(const Transform& globalTransform); - virtual bool needsBlending() const; - virtual bool isSecure() const { return false; } -private: - void drawScaled(float angle, float scale, float alpha) const; - - OrientationAnimation* mAnim; - sp mBitmapIn; - sp mBitmapOut; - nsecs_t mStartTime; - nsecs_t mFinishTime; - bool mOrientationCompleted; - int mOriginalTargetOrientation; - mutable bool mFirstRedraw; - mutable float mLastNormalizedTime; - mutable float mLastAngle; - mutable float mLastScale; - mutable GLuint mTextureName; - mutable GLuint mTextureNameIn; - mutable bool mNeedsBlending; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp deleted file mode 100644 index a6c9c28d0ba8..000000000000 --- a/libs/surfaceflinger/OrientationAnimation.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2007 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 - -#include "LayerOrientationAnim.h" -#include "LayerOrientationAnimRotate.h" -#include "OrientationAnimation.h" -#include "SurfaceFlinger.h" - -#include "DisplayHardware/DisplayHardware.h" - -namespace android { - -// --------------------------------------------------------------------------- - -OrientationAnimation::OrientationAnimation(const sp& flinger) - : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) -{ -} - -OrientationAnimation::~OrientationAnimation() -{ -} - -void OrientationAnimation::onOrientationChanged(uint32_t type) -{ - if (mState == DONE) { - mType = type; - if (!(type & ISurfaceComposer::eOrientationAnimationDisable)) { - mState = PREPARE; - } - } -} - -void OrientationAnimation::onAnimationFinished() -{ - if (mState != DONE) - mState = FINISH; -} - -bool OrientationAnimation::run_impl() -{ - bool skip_frame; - switch (mState) { - default: - case DONE: - skip_frame = done(); - break; - case PREPARE: - skip_frame = prepare(); - break; - case PHASE1: - skip_frame = phase1(); - break; - case PHASE2: - skip_frame = phase2(); - break; - case FINISH: - skip_frame = finished(); - break; - } - return skip_frame; -} - -bool OrientationAnimation::done() -{ - return done_impl(); -} - -bool OrientationAnimation::prepare() -{ - mState = PHASE1; - - const GraphicPlane& plane(mFlinger->graphicPlane(0)); - const DisplayHardware& hw(plane.displayHardware()); - const uint32_t w = hw.getWidth(); - const uint32_t h = hw.getHeight(); - - sp bitmap = new Buffer(w, h, hw.getFormat()); - sp bitmapIn = new Buffer(w, h, hw.getFormat()); - - copybit_image_t front; - bitmap->getBitmapSurface(&front); - hw.copyFrontToImage(front); // FIXME: we need an extension to do this - - sp l; - - if (mType & 0x80) { - l = new LayerOrientationAnimRotate( - mFlinger.get(), 0, this, bitmap, bitmapIn); - } else { - l = new LayerOrientationAnim( - mFlinger.get(), 0, this, bitmap, bitmapIn); - } - - l->initStates(w, h, 0); - l->setLayer(INT_MAX-1); - mFlinger->addLayer(l); - mLayerOrientationAnim = l; - return true; -} - -bool OrientationAnimation::phase1() -{ - if (mFlinger->isFrozen() == false) { - // start phase 2 - mState = PHASE2; - mLayerOrientationAnim->onOrientationCompleted(); - mLayerOrientationAnim->invalidate(); - return true; - - } - mLayerOrientationAnim->invalidate(); - return false; -} - -bool OrientationAnimation::phase2() -{ - // do the 2nd phase of the animation - mLayerOrientationAnim->invalidate(); - return false; -} - -bool OrientationAnimation::finished() -{ - mState = DONE; - mFlinger->removeLayer(mLayerOrientationAnim); - mLayerOrientationAnim.clear(); - return true; -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h deleted file mode 100644 index 8ba66210e873..000000000000 --- a/libs/surfaceflinger/OrientationAnimation.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -#ifndef ANDROID_ORIENTATION_ANIMATION_H -#define ANDROID_ORIENTATION_ANIMATION_H - -#include -#include - -#include "SurfaceFlinger.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class SurfaceFlinger; -class MemoryDealer; -class LayerOrientationAnim; - -class OrientationAnimation -{ -public: - OrientationAnimation(const sp& flinger); - virtual ~OrientationAnimation(); - - void onOrientationChanged(uint32_t type); - void onAnimationFinished(); - inline bool run() { - if (LIKELY(mState == DONE)) - return done_impl(); - return run_impl(); - } - -private: - enum { - DONE = 0, - PREPARE, - PHASE1, - PHASE2, - FINISH - }; - - bool run_impl(); - inline bool done_impl() { - if (mFlinger->isFrozen()) { - // we are not allowed to draw, but pause a bit to make sure - // apps don't end up using the whole CPU, if they depend on - // surfaceflinger for synchronization. - usleep(8333); // 8.3ms ~ 120fps - return true; - } - return false; - } - - bool done(); - bool prepare(); - bool phase1(); - bool phase2(); - bool finished(); - - sp mFlinger; - sp< LayerOrientationAnimBase > mLayerOrientationAnim; - int mState; - uint32_t mType; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_ORIENTATION_ANIMATION_H diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 6b421588e19c..5fd979e0614b 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -50,8 +50,6 @@ #include "LayerBuffer.h" #include "LayerDim.h" #include "LayerBitmap.h" -#include "LayerOrientationAnim.h" -#include "OrientationAnimation.h" #include "SurfaceFlinger.h" #include "DisplayHardware/DisplayHardware.h" @@ -206,7 +204,6 @@ void SurfaceFlinger::init() SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); - delete mOrientationAnimation; } overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const @@ -399,8 +396,6 @@ status_t SurfaceFlinger::readyToRun() * We're now ready to accept clients... */ - mOrientationAnimation = new OrientationAnimation(this); - // the boot animation! if (mDebugNoBootAnimation == false) mBootAnimation = new BootAnimation(this); @@ -513,16 +508,17 @@ bool SurfaceFlinger::threadLoop() void SurfaceFlinger::postFramebuffer() { - const bool skip = mOrientationAnimation->run(); - if (UNLIKELY(skip)) { + if (isFrozen()) { + // we are not allowed to draw, but pause a bit to make sure + // apps don't end up using the whole CPU, if they depend on + // surfaceflinger for synchronization. + usleep(8333); // 8.3ms ~ 120fps return; } if (!mInvalidRegion.isEmpty()) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); - hw.flip(mInvalidRegion); - mInvalidRegion.clear(); } } @@ -616,7 +612,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mVisibleRegionsDirty = true; mDirtyRegion.set(hw.bounds()); mFreezeDisplayTime = 0; - mOrientationAnimation->onOrientationChanged(type); } if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { @@ -893,19 +888,26 @@ void SurfaceFlinger::executeScheduledBroadcasts() void SurfaceFlinger::debugFlashRegions() { - if (UNLIKELY(!mDirtyRegion.isRect())) { - // TODO: do this only if we don't have preserving - // swapBuffer. If we don't have update-on-demand, - // redraw everything. - composeSurfaces(Region(mDirtyRegion.bounds())); - } - + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + const uint32_t flags = hw.getFlags(); + if (!(flags & DisplayHardware::BUFFER_PRESERVED)) { + const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ? + mDirtyRegion.bounds() : hw.bounds()); + composeSurfaces(repaint); + } + glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDisable(GL_DITHER); glDisable(GL_SCISSOR_TEST); - glColor4x(0x10000, 0, 0x10000, 0x10000); + static int toggle = 0; + toggle = 1 - toggle; + if (toggle) { + glColor4x(0x10000, 0, 0x10000, 0x10000); + } else { + glColor4x(0x10000, 0x10000, 0, 0x10000); + } Rect r; Region::iterator iterator(mDirtyRegion); @@ -919,8 +921,7 @@ void SurfaceFlinger::debugFlashRegions() glVertexPointer(2, GL_FLOAT, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - - const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.flip(mDirtyRegion.merge(mInvalidRegion)); mInvalidRegion.clear(); diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index 319f80e9e926..d5e525273c77 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -55,8 +55,6 @@ class DisplayHardware; class FreezeLock; class Layer; class LayerBuffer; -class LayerOrientationAnim; -class OrientationAnimation; typedef int32_t ClientID; @@ -335,8 +333,6 @@ private: bool mFreezeDisplay; int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; - friend class OrientationAnimation; - OrientationAnimation* mOrientationAnimation; // don't use a lock for these, we don't care int mDebugRegion; diff --git a/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp new file mode 100644 index 000000000000..41c42d177573 --- /dev/null +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2007 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. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include +#include +#include + +#include +#include +#include + +#include "BlurFilter.h" +#include "LayerBase.h" +#include "LayerOrientationAnim.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/DisplayHardware.h" +#include "OrientationAnimation.h" + +namespace android { +// --------------------------------------------------------------------------- + +const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80; +const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; + +// --------------------------------------------------------------------------- + +// Animation... +const float DURATION = ms2ns(200); +const float BOUNCES_PER_SECOND = 0.5f; +//const float BOUNCES_AMPLITUDE = 1.0f/16.0f; +const float BOUNCES_AMPLITUDE = 0; +const float DIM_TARGET = 0.40f; +//#define INTERPOLATED_TIME(_t) ((_t)*(_t)) +#define INTERPOLATED_TIME(_t) (_t) + +// --------------------------------------------------------------------------- + +LayerOrientationAnim::LayerOrientationAnim( + SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const sp& bitmapIn, + const sp& bitmapOut) + : LayerOrientationAnimBase(flinger, display), mAnim(anim), + mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), + mTextureName(-1), mTextureNameIn(-1) +{ + // blur that texture. + mStartTime = systemTime(); + mFinishTime = 0; + mOrientationCompleted = false; + mFirstRedraw = false; + mLastNormalizedTime = 0; + mNeedsBlending = false; + mAlphaInLerp.set(1.0f, DIM_TARGET); + mAlphaOutLerp.set(0.5f, 1.0f); +} + +LayerOrientationAnim::~LayerOrientationAnim() +{ + if (mTextureName != -1U) { + glDeleteTextures(1, &mTextureName); + } + if (mTextureNameIn != -1U) { + glDeleteTextures(1, &mTextureNameIn); + } +} + +bool LayerOrientationAnim::needsBlending() const +{ + return mNeedsBlending; +} + +Point LayerOrientationAnim::getPhysicalSize() const +{ + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + return Point(hw.getWidth(), hw.getHeight()); +} + +void LayerOrientationAnim::validateVisibility(const Transform&) +{ + const Layer::State& s(drawingState()); + const Transform tr(s.transform); + const Point size(getPhysicalSize()); + uint32_t w = size.x; + uint32_t h = size.y; + mTransformedBounds = tr.makeBounds(w, h); + mLeft = tr.tx(); + mTop = tr.ty(); + transparentRegionScreen.clear(); + mTransformed = true; +} + +void LayerOrientationAnim::onOrientationCompleted() +{ + mFinishTime = systemTime(); + mOrientationCompleted = true; + mFirstRedraw = true; + mNeedsBlending = true; + mFlinger->invalidateLayerVisibility(this); +} + +void LayerOrientationAnim::onDraw(const Region& clip) const +{ + const nsecs_t now = systemTime(); + float alphaIn, alphaOut; + + if (mOrientationCompleted) { + if (mFirstRedraw) { + mFirstRedraw = false; + + // make a copy of what's on screen + copybit_image_t image; + mBitmapOut->getBitmapSurface(&image); + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.copyBackToImage(image); + + // and erase the screen for this round + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + // FIXME: code below is gross + mNeedsBlending = false; + LayerOrientationAnim* self(const_cast(this)); + mFlinger->invalidateLayerVisibility(self); + } + + // make sure pick-up where we left off + const float duration = DURATION * mLastNormalizedTime; + const float normalizedTime = (float(now - mFinishTime) / duration); + if (normalizedTime <= 1.0f) { + const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); + alphaIn = mAlphaInLerp.getOut(); + alphaOut = mAlphaOutLerp(interpolatedTime); + } else { + mAnim->onAnimationFinished(); + alphaIn = mAlphaInLerp.getOut(); + alphaOut = mAlphaOutLerp.getOut(); + } + } else { + const float normalizedTime = float(now - mStartTime) / DURATION; + if (normalizedTime <= 1.0f) { + mLastNormalizedTime = normalizedTime; + const float interpolatedTime = INTERPOLATED_TIME(normalizedTime); + alphaIn = mAlphaInLerp(interpolatedTime); + alphaOut = 0.0f; + } else { + mLastNormalizedTime = 1.0f; + const float to_seconds = DURATION / seconds(1); + alphaIn = mAlphaInLerp.getOut(); + if (BOUNCES_AMPLITUDE > 0.0f) { + const float phi = BOUNCES_PER_SECOND * + (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); + if (alphaIn > 1.0f) alphaIn = 1.0f; + else if (alphaIn < 0.0f) alphaIn = 0.0f; + alphaIn += BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); + } + alphaOut = 0.0f; + } + mAlphaOutLerp.setIn(alphaIn); + } + drawScaled(1.0f, alphaIn, alphaOut); +} + +void LayerOrientationAnim::drawScaled(float scale, float alphaIn, float alphaOut) const +{ + copybit_image_t dst; + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + //hw.getDisplaySurface(&dst); + + // clear screen + // TODO: with update on demand, we may be able + // to not erase the screen at all during the animation + if (!mOrientationCompleted) { + if (scale==1.0f && (alphaIn>=1.0f || alphaOut>=1.0f)) { + // we don't need to erase the screen in that case + } else { + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + } + } + + copybit_image_t src; + mBitmapIn->getBitmapSurface(&src); + + copybit_image_t srcOut; + mBitmapOut->getBitmapSurface(&srcOut); + + const int w = dst.w*scale; + const int h = dst.h*scale; + const int xc = uint32_t(dst.w-w)/2; + const int yc = uint32_t(dst.h-h)/2; + const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; + const copybit_rect_t srect = { 0, 0, src.w, src.h }; + const Region reg(Rect( drect.l, drect.t, drect.r, drect.b )); + + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + + Transform tr; + tr.set(scale,0,0,scale); + tr.set(xc, yc); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnim& self(const_cast(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; + } + + if (alphaIn > 0.0f) { + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); + } + self.mDrawingState.alpha = int(alphaIn*255); + drawWithOpenGL(reg, mTextureNameIn, t); + } + + if (alphaOut > 0.0f) { + t.data = (GGLubyte*)(intptr_t(srcOut.base) + srcOut.offset); + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); + } + self.mDrawingState.alpha = int(alphaOut*255); + drawWithOpenGL(reg, mTextureName, t); + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/purgatory/LayerOrientationAnim.h b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h new file mode 100644 index 000000000000..472c45a1afef --- /dev/null +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnim.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_LAYER_ORIENTATION_ANIM_H +#define ANDROID_LAYER_ORIENTATION_ANIM_H + +#include +#include +#include +#include + +#include "LayerBase.h" +#include "LayerBitmap.h" + +namespace android { + +// --------------------------------------------------------------------------- +class OrientationAnimation; + + +class LayerOrientationAnimBase : public LayerBase +{ +public: + LayerOrientationAnimBase(SurfaceFlinger* flinger, DisplayID display) + : LayerBase(flinger, display) { + } + virtual void onOrientationCompleted() = 0; +}; + +// --------------------------------------------------------------------------- + +class LayerOrientationAnim : public LayerOrientationAnimBase +{ +public: + static const uint32_t typeInfo; + static const char* const typeID; + virtual char const* getTypeID() const { return typeID; } + virtual uint32_t getTypeInfo() const { return typeInfo; } + + LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const sp& bitmapIn, + const sp& bitmapOut); + virtual ~LayerOrientationAnim(); + + void onOrientationCompleted(); + + virtual void onDraw(const Region& clip) const; + virtual Point getPhysicalSize() const; + virtual void validateVisibility(const Transform& globalTransform); + virtual bool needsBlending() const; + virtual bool isSecure() const { return false; } +private: + void drawScaled(float scale, float alphaIn, float alphaOut) const; + + class Lerp { + float in; + float outMinusIn; + public: + Lerp() : in(0), outMinusIn(0) { } + Lerp(float in, float out) : in(in), outMinusIn(out-in) { } + float getIn() const { return in; }; + float getOut() const { return in + outMinusIn; } + void set(float in, float out) { + this->in = in; + this->outMinusIn = out-in; + } + void setIn(float in) { + this->in = in; + } + void setOut(float out) { + this->outMinusIn = out - this->in; + } + float operator()(float t) const { + return outMinusIn*t + in; + } + }; + + OrientationAnimation* mAnim; + sp mBitmapIn; + sp mBitmapOut; + nsecs_t mStartTime; + nsecs_t mFinishTime; + bool mOrientationCompleted; + mutable bool mFirstRedraw; + mutable float mLastNormalizedTime; + mutable GLuint mTextureName; + mutable GLuint mTextureNameIn; + mutable bool mNeedsBlending; + + mutable Lerp mAlphaInLerp; + mutable Lerp mAlphaOutLerp; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_LAYER_ORIENTATION_ANIM_H diff --git a/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp new file mode 100644 index 000000000000..dc6b632a694d --- /dev/null +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2007 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. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include +#include +#include + +#include +#include + +#include "LayerBase.h" +#include "LayerOrientationAnim.h" +#include "LayerOrientationAnimRotate.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/DisplayHardware.h" +#include "OrientationAnimation.h" + +namespace android { +// --------------------------------------------------------------------------- + +const uint32_t LayerOrientationAnimRotate::typeInfo = LayerBase::typeInfo | 0x100; +const char* const LayerOrientationAnimRotate::typeID = "LayerOrientationAnimRotate"; + +// --------------------------------------------------------------------------- + +const float ROTATION = M_PI * 0.5f; +const float ROTATION_FACTOR = 1.0f; // 1.0 or 2.0 +const float DURATION = ms2ns(200); +const float BOUNCES_PER_SECOND = 0.8; +const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI; + +LayerOrientationAnimRotate::LayerOrientationAnimRotate( + SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const sp& bitmapIn, + const sp& bitmapOut) + : LayerOrientationAnimBase(flinger, display), mAnim(anim), + mBitmapIn(bitmapIn), mBitmapOut(bitmapOut), + mTextureName(-1), mTextureNameIn(-1) +{ + mStartTime = systemTime(); + mFinishTime = 0; + mOrientationCompleted = false; + mFirstRedraw = false; + mLastNormalizedTime = 0; + mLastAngle = 0; + mLastScale = 0; + mNeedsBlending = false; + const GraphicPlane& plane(graphicPlane(0)); + mOriginalTargetOrientation = plane.getOrientation(); +} + +LayerOrientationAnimRotate::~LayerOrientationAnimRotate() +{ + if (mTextureName != -1U) { + glDeleteTextures(1, &mTextureName); + } + if (mTextureNameIn != -1U) { + glDeleteTextures(1, &mTextureNameIn); + } +} + +bool LayerOrientationAnimRotate::needsBlending() const +{ + return mNeedsBlending; +} + +Point LayerOrientationAnimRotate::getPhysicalSize() const +{ + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + return Point(hw.getWidth(), hw.getHeight()); +} + +void LayerOrientationAnimRotate::validateVisibility(const Transform&) +{ + const Layer::State& s(drawingState()); + const Transform tr(s.transform); + const Point size(getPhysicalSize()); + uint32_t w = size.x; + uint32_t h = size.y; + mTransformedBounds = tr.makeBounds(w, h); + mLeft = tr.tx(); + mTop = tr.ty(); + transparentRegionScreen.clear(); + mTransformed = true; +} + +void LayerOrientationAnimRotate::onOrientationCompleted() +{ + mFinishTime = systemTime(); + mOrientationCompleted = true; + mFirstRedraw = true; + mNeedsBlending = true; + mFlinger->invalidateLayerVisibility(this); +} + +void LayerOrientationAnimRotate::onDraw(const Region& clip) const +{ + // Animation... + + const nsecs_t now = systemTime(); + float angle, scale, alpha; + + if (mOrientationCompleted) { + if (mFirstRedraw) { + // make a copy of what's on screen + copybit_image_t image; + mBitmapIn->getBitmapSurface(&image); + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.copyBackToImage(image); + + // FIXME: code below is gross + mFirstRedraw = false; + mNeedsBlending = false; + LayerOrientationAnimRotate* self(const_cast(this)); + mFlinger->invalidateLayerVisibility(self); + } + + // make sure pick-up where we left off + const float duration = DURATION * mLastNormalizedTime; + const float normalizedTime = (float(now - mFinishTime) / duration); + if (normalizedTime <= 1.0f) { + const float squaredTime = normalizedTime*normalizedTime; + angle = (ROTATION*ROTATION_FACTOR - mLastAngle)*squaredTime + mLastAngle; + scale = (1.0f - mLastScale)*squaredTime + mLastScale; + alpha = normalizedTime; + } else { + mAnim->onAnimationFinished(); + angle = ROTATION; + alpha = 1.0f; + scale = 1.0f; + } + } else { + // FIXME: works only for portrait framebuffers + const Point size(getPhysicalSize()); + const float TARGET_SCALE = size.x * (1.0f / size.y); + const float normalizedTime = float(now - mStartTime) / DURATION; + if (normalizedTime <= 1.0f) { + mLastNormalizedTime = normalizedTime; + const float squaredTime = normalizedTime*normalizedTime; + angle = ROTATION * squaredTime; + scale = (TARGET_SCALE - 1.0f)*squaredTime + 1.0f; + alpha = 0; + } else { + mLastNormalizedTime = 1.0f; + angle = ROTATION; + if (BOUNCES_AMPLITUDE) { + const float to_seconds = DURATION / seconds(1); + const float phi = BOUNCES_PER_SECOND * + (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); + angle += BOUNCES_AMPLITUDE * sinf(phi); + } + scale = TARGET_SCALE; + alpha = 0; + } + mLastAngle = angle; + mLastScale = scale; + } + drawScaled(angle, scale, alpha); +} + +void LayerOrientationAnimRotate::drawScaled(float f, float s, float alpha) const +{ + copybit_image_t dst; + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + //hw.getDisplaySurface(&dst); + + // clear screen + // TODO: with update on demand, we may be able + // to not erase the screen at all during the animation + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + const int w = dst.w; + const int h = dst.h; + + copybit_image_t src; + mBitmapIn->getBitmapSurface(&src); + const copybit_rect_t srect = { 0, 0, src.w, src.h }; + + + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + + if (!mOriginalTargetOrientation) { + f = -f; + } + + Transform tr; + tr.set(f, w*0.5f, h*0.5f); + tr.scale(s, w*0.5f, h*0.5f); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnimRotate& self(const_cast(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; + } + + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); + } + self.mDrawingState.alpha = 255; //-int(alpha*255); + const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); + drawWithOpenGL(clip, mTextureName, t); + + if (alpha > 0) { + const float sign = (!mOriginalTargetOrientation) ? 1.0f : -1.0f; + tr.set(f + sign*(M_PI * 0.5f * ROTATION_FACTOR), w*0.5f, h*0.5f); + tr.scale(s, w*0.5f, h*0.5f); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + + copybit_image_t src; + mBitmapIn->getBitmapSurface(&src); + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); + } + self.mDrawingState.alpha = int(alpha*255); + const Region clip(Rect( srect.l, srect.t, srect.r, srect.b )); + drawWithOpenGL(clip, mTextureNameIn, t); + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h new file mode 100644 index 000000000000..a675c79b5176 --- /dev/null +++ b/libs/surfaceflinger/purgatory/LayerOrientationAnimRotate.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H +#define ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H + +#include +#include +#include +#include + +#include "LayerBase.h" +#include "LayerBitmap.h" + +namespace android { + +// --------------------------------------------------------------------------- +class OrientationAnimation; + +class LayerOrientationAnimRotate : public LayerOrientationAnimBase +{ +public: + static const uint32_t typeInfo; + static const char* const typeID; + virtual char const* getTypeID() const { return typeID; } + virtual uint32_t getTypeInfo() const { return typeInfo; } + + LayerOrientationAnimRotate(SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const sp& bitmapIn, + const sp& bitmapOut); + virtual ~LayerOrientationAnimRotate(); + + void onOrientationCompleted(); + + virtual void onDraw(const Region& clip) const; + virtual Point getPhysicalSize() const; + virtual void validateVisibility(const Transform& globalTransform); + virtual bool needsBlending() const; + virtual bool isSecure() const { return false; } +private: + void drawScaled(float angle, float scale, float alpha) const; + + OrientationAnimation* mAnim; + sp mBitmapIn; + sp mBitmapOut; + nsecs_t mStartTime; + nsecs_t mFinishTime; + bool mOrientationCompleted; + int mOriginalTargetOrientation; + mutable bool mFirstRedraw; + mutable float mLastNormalizedTime; + mutable float mLastAngle; + mutable float mLastScale; + mutable GLuint mTextureName; + mutable GLuint mTextureNameIn; + mutable bool mNeedsBlending; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_LAYER_ORIENTATION_ANIM_ROTATE_H diff --git a/libs/surfaceflinger/purgatory/OrientationAnimation.cpp b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp new file mode 100644 index 000000000000..a6c9c28d0ba8 --- /dev/null +++ b/libs/surfaceflinger/purgatory/OrientationAnimation.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2007 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 + +#include "LayerOrientationAnim.h" +#include "LayerOrientationAnimRotate.h" +#include "OrientationAnimation.h" +#include "SurfaceFlinger.h" + +#include "DisplayHardware/DisplayHardware.h" + +namespace android { + +// --------------------------------------------------------------------------- + +OrientationAnimation::OrientationAnimation(const sp& flinger) + : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) +{ +} + +OrientationAnimation::~OrientationAnimation() +{ +} + +void OrientationAnimation::onOrientationChanged(uint32_t type) +{ + if (mState == DONE) { + mType = type; + if (!(type & ISurfaceComposer::eOrientationAnimationDisable)) { + mState = PREPARE; + } + } +} + +void OrientationAnimation::onAnimationFinished() +{ + if (mState != DONE) + mState = FINISH; +} + +bool OrientationAnimation::run_impl() +{ + bool skip_frame; + switch (mState) { + default: + case DONE: + skip_frame = done(); + break; + case PREPARE: + skip_frame = prepare(); + break; + case PHASE1: + skip_frame = phase1(); + break; + case PHASE2: + skip_frame = phase2(); + break; + case FINISH: + skip_frame = finished(); + break; + } + return skip_frame; +} + +bool OrientationAnimation::done() +{ + return done_impl(); +} + +bool OrientationAnimation::prepare() +{ + mState = PHASE1; + + const GraphicPlane& plane(mFlinger->graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + const uint32_t w = hw.getWidth(); + const uint32_t h = hw.getHeight(); + + sp bitmap = new Buffer(w, h, hw.getFormat()); + sp bitmapIn = new Buffer(w, h, hw.getFormat()); + + copybit_image_t front; + bitmap->getBitmapSurface(&front); + hw.copyFrontToImage(front); // FIXME: we need an extension to do this + + sp l; + + if (mType & 0x80) { + l = new LayerOrientationAnimRotate( + mFlinger.get(), 0, this, bitmap, bitmapIn); + } else { + l = new LayerOrientationAnim( + mFlinger.get(), 0, this, bitmap, bitmapIn); + } + + l->initStates(w, h, 0); + l->setLayer(INT_MAX-1); + mFlinger->addLayer(l); + mLayerOrientationAnim = l; + return true; +} + +bool OrientationAnimation::phase1() +{ + if (mFlinger->isFrozen() == false) { + // start phase 2 + mState = PHASE2; + mLayerOrientationAnim->onOrientationCompleted(); + mLayerOrientationAnim->invalidate(); + return true; + + } + mLayerOrientationAnim->invalidate(); + return false; +} + +bool OrientationAnimation::phase2() +{ + // do the 2nd phase of the animation + mLayerOrientationAnim->invalidate(); + return false; +} + +bool OrientationAnimation::finished() +{ + mState = DONE; + mFlinger->removeLayer(mLayerOrientationAnim); + mLayerOrientationAnim.clear(); + return true; +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/purgatory/OrientationAnimation.h b/libs/surfaceflinger/purgatory/OrientationAnimation.h new file mode 100644 index 000000000000..8ba66210e873 --- /dev/null +++ b/libs/surfaceflinger/purgatory/OrientationAnimation.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_ORIENTATION_ANIMATION_H +#define ANDROID_ORIENTATION_ANIMATION_H + +#include +#include + +#include "SurfaceFlinger.h" + +namespace android { + +// --------------------------------------------------------------------------- + +class SurfaceFlinger; +class MemoryDealer; +class LayerOrientationAnim; + +class OrientationAnimation +{ +public: + OrientationAnimation(const sp& flinger); + virtual ~OrientationAnimation(); + + void onOrientationChanged(uint32_t type); + void onAnimationFinished(); + inline bool run() { + if (LIKELY(mState == DONE)) + return done_impl(); + return run_impl(); + } + +private: + enum { + DONE = 0, + PREPARE, + PHASE1, + PHASE2, + FINISH + }; + + bool run_impl(); + inline bool done_impl() { + if (mFlinger->isFrozen()) { + // we are not allowed to draw, but pause a bit to make sure + // apps don't end up using the whole CPU, if they depend on + // surfaceflinger for synchronization. + usleep(8333); // 8.3ms ~ 120fps + return true; + } + return false; + } + + bool done(); + bool prepare(); + bool phase1(); + bool phase2(); + bool finished(); + + sp mFlinger; + sp< LayerOrientationAnimBase > mLayerOrientationAnim; + int mState; + uint32_t mType; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_ORIENTATION_ANIMATION_H diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index 577dd4bf7904..d44d2f965be4 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -5,9 +5,9 @@ LOCAL_SRC_FILES:= \ BufferMapper.cpp \ Camera.cpp \ CameraParameters.cpp \ - EGLNativeWindowSurface.cpp \ EventHub.cpp \ EventRecurrence.cpp \ + FramebufferNativeWindow.cpp \ KeyLayoutMap.cpp \ KeyCharacterMap.cpp \ ICamera.cpp \ diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp index 85a029bcc0d2..1a75c5d9acdf 100644 --- a/libs/ui/BufferMapper.cpp +++ b/libs/ui/BufferMapper.cpp @@ -17,14 +17,9 @@ #define LOG_TAG "BufferMapper" #include -#include -#include #include -#include -#include #include -#include #include #include @@ -34,12 +29,6 @@ #include -// --------------------------------------------------------------------------- -// enable mapping debugging -#define DEBUG_MAPPINGS 0 -// never remove mappings from the list -#define DEBUG_MAPPINGS_KEEP_ALL 0 -// --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- @@ -57,34 +46,27 @@ BufferMapper::BufferMapper() } } -status_t BufferMapper::map(buffer_handle_t handle, void** addr, const void* id) +status_t BufferMapper::registerBuffer(buffer_handle_t handle) { - Mutex::Autolock _l(mLock); - status_t err = mAllocMod->map(mAllocMod, handle, addr); - LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); -#if DEBUG_MAPPINGS - if (err == NO_ERROR) - logMapLocked(handle, id); -#endif + status_t err = mAllocMod->registerBuffer(mAllocMod, handle); + LOGW_IF(err, "registerBuffer(%p) failed %d (%s)", + handle, err, strerror(-err)); return err; } -status_t BufferMapper::unmap(buffer_handle_t handle, const void* id) +status_t BufferMapper::unregisterBuffer(buffer_handle_t handle) { - Mutex::Autolock _l(mLock); - status_t err = mAllocMod->unmap(mAllocMod, handle); - LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); -#if DEBUG_MAPPINGS - if (err == NO_ERROR) - logUnmapLocked(handle, id); -#endif + status_t err = mAllocMod->unregisterBuffer(mAllocMod, handle); + LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)", + handle, err, strerror(-err)); return err; } -status_t BufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds) +status_t BufferMapper::lock(buffer_handle_t handle, + int usage, const Rect& bounds, void** vaddr) { status_t err = mAllocMod->lock(mAllocMod, handle, usage, - bounds.left, bounds.top, bounds.width(), bounds.height()); + bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); return err; } @@ -96,65 +78,5 @@ status_t BufferMapper::unlock(buffer_handle_t handle) return err; } -void BufferMapper::logMapLocked(buffer_handle_t handle, const void* id) -{ - CallStack stack; - stack.update(2); - - map_info_t info; - info.id = id; - info.stack = stack; - - ssize_t index = mMapInfo.indexOfKey(handle); - if (index >= 0) { - Vector& infos = mMapInfo.editValueAt(index); - infos.add(info); - } else { - Vector infos; - infos.add(info); - mMapInfo.add(handle, infos); - } -} - -void BufferMapper::logUnmapLocked(buffer_handle_t handle, const void* id) -{ - ssize_t index = mMapInfo.indexOfKey(handle); - if (index < 0) { - LOGE("unmapping %p which doesn't exist in our map!", handle); - return; - } - - Vector& infos = mMapInfo.editValueAt(index); - ssize_t count = infos.size(); - for (int i=0 ; i& infos = mMapInfo.valueAt(index); - ssize_t count = infos.size(); - for (int i=0 ; i -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -/* - * This implements the (main) framebuffer management. This class is used - * mostly by SurfaceFlinger, but also by command line GL application. - * - * In fact this is an implementation of android_native_window_t on top of - * the framebuffer. - * - * Currently it is pretty simple, it manages only two buffers (the front and - * back buffer). - * - */ - -FramebufferNativeWindow::FramebufferNativeWindow() - : BASE(), fbDev(0), grDev(0) -{ - hw_module_t const* module; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { - int stride; - framebuffer_open(module, &fbDev); - gralloc_open(module, &grDev); - int err; - - - // initialize the buffer FIFO - mNumBuffers = 2; - mNumFreeBuffers = 2; - mBufferHead = mNumBuffers-1; - buffers[0] = new NativeBuffer( - fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); - buffers[1] = new NativeBuffer( - fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); - - err = grDev->alloc(grDev, - fbDev->width, fbDev->height, fbDev->format, - GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); - - LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", - fbDev->width, fbDev->height, strerror(-err)); - - err = grDev->alloc(grDev, - fbDev->width, fbDev->height, fbDev->format, - GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); - - LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", - fbDev->width, fbDev->height, strerror(-err)); - - gralloc_module_t* m = - reinterpret_cast(grDev->common.module); - - // FIXME: do we actually need to map the framebuffer? - m->map(m, buffers[0]->handle, &buffers[0]->bits); - m->map(m, buffers[1]->handle, &buffers[1]->bits); - } - - uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED; - - /* - * FIXME: SURFACE_FLAG_PRESERVE_CONTENT - * how to implement this, there is no concept of preserve content in - * the framebuffer, which just "posts" buffer. - * - * It looks like what we need is a way to know if the posted buffer can - * be reused. But if so, why allocating 2 buffers?... - * - * should the lock/unlock calls take care of the copy-back? - * - * - * In the end, the client wants to know if the backbuffer is preserved - * though... it's complicated. - * - */ - - //flags |= SURFACE_FLAG_PRESERVE_CONTENT; - - - const_cast(android_native_window_t::flags) = flags; - const_cast(android_native_window_t::xdpi) = fbDev->xdpi; - const_cast(android_native_window_t::ydpi) = fbDev->ydpi; - const_cast(android_native_window_t::minSwapInterval) = - fbDev->minSwapInterval; - const_cast(android_native_window_t::maxSwapInterval) = - fbDev->maxSwapInterval; - - android_native_window_t::connect = connect; - android_native_window_t::disconnect = disconnect; - android_native_window_t::setSwapInterval = setSwapInterval; - android_native_window_t::setSwapRectangle = setSwapRectangle; - android_native_window_t::dequeueBuffer = dequeueBuffer; - android_native_window_t::lockBuffer = lockBuffer; - android_native_window_t::queueBuffer = queueBuffer; -} - -FramebufferNativeWindow::~FramebufferNativeWindow() { - grDev->free(grDev, buffers[0]->handle); - grDev->free(grDev, buffers[1]->handle); - gralloc_module_t* m = - reinterpret_cast(grDev->common.module); - m->unmap(m, buffers[0]->handle); - m->unmap(m, buffers[1]->handle); - gralloc_close(grDev); - framebuffer_close(fbDev); -} - -void FramebufferNativeWindow::connect(android_native_window_t* window) -{ -} - -void FramebufferNativeWindow::disconnect(android_native_window_t* window) -{ -} - -int FramebufferNativeWindow::setSwapInterval( - android_native_window_t* window, int interval) -{ - framebuffer_device_t* fb = getSelf(window)->fbDev; - return fb->setSwapInterval(fb, interval); -} - -int FramebufferNativeWindow::setSwapRectangle(android_native_window_t* window, - int l, int t, int w, int h) -{ - FramebufferNativeWindow* self = getSelf(window); - Mutex::Autolock _l(self->mutex); - self->mDirty = Rect(l, t, l+w, t+h); - return 0; -} - -int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, - android_native_buffer_t** buffer) -{ - FramebufferNativeWindow* self = getSelf(window); - Mutex::Autolock _l(self->mutex); - framebuffer_device_t* fb = self->fbDev; - - // wait for a free buffer - while (!self->mNumFreeBuffers) { - self->mCondition.wait(self->mutex); - } - // get this buffer - self->mNumFreeBuffers--; - int index = self->mBufferHead++; - if (self->mBufferHead >= self->mNumBuffers) - self->mBufferHead = 0; - - *buffer = self->buffers[index].get(); - - return 0; -} - -int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, - android_native_buffer_t* buffer) -{ - FramebufferNativeWindow* self = getSelf(window); - Mutex::Autolock _l(self->mutex); - - // wait that the buffer we're locking is not front anymore - while (self->front == buffer) { - self->mCondition.wait(self->mutex); - } - - gralloc_module_t* m = - reinterpret_cast(self->grDev->common.module); - const Rect& dirty(self->mDirty); - - buffer_handle_t handle = static_cast(buffer)->handle; - int res = m->lock(m, handle, GRALLOC_USAGE_HW_FB, - dirty.left, dirty.right, dirty.width(), dirty.height()); - - return res; -} - -int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, - android_native_buffer_t* buffer) -{ - FramebufferNativeWindow* self = getSelf(window); - Mutex::Autolock _l(self->mutex); - framebuffer_device_t* fb = self->fbDev; - gralloc_module_t* m = - reinterpret_cast(self->grDev->common.module); - - buffer_handle_t handle = static_cast(buffer)->handle; - m->unlock(m, handle); - int res = fb->post(fb, handle); - - self->front = static_cast(buffer); - self->mNumFreeBuffers++; - self->mCondition.broadcast(); - return res; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- - - -EGLNativeWindowType android_createDisplaySurface(void) -{ - return new android::FramebufferNativeWindow(); -} - diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp new file mode 100644 index 000000000000..407d6f4f2b19 --- /dev/null +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -0,0 +1,214 @@ +/* +** +** Copyright 2007 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. +*/ + +#define LOG_TAG "FramebufferNativeWindow" + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +/* + * This implements the (main) framebuffer management. This class is used + * mostly by SurfaceFlinger, but also by command line GL application. + * + * In fact this is an implementation of android_native_window_t on top of + * the framebuffer. + * + * Currently it is pretty simple, it manages only two buffers (the front and + * back buffer). + * + */ + +FramebufferNativeWindow::FramebufferNativeWindow() + : BASE(), fbDev(0), grDev(0) +{ + hw_module_t const* module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + int stride; + framebuffer_open(module, &fbDev); + gralloc_open(module, &grDev); + int err; + + + // initialize the buffer FIFO + mNumBuffers = 2; + mNumFreeBuffers = 2; + mBufferHead = mNumBuffers-1; + buffers[0] = new NativeBuffer( + fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + buffers[1] = new NativeBuffer( + fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB); + + err = grDev->alloc(grDev, + fbDev->width, fbDev->height, fbDev->format, + GRALLOC_USAGE_HW_FB, &buffers[0]->handle, &buffers[0]->stride); + + LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s", + fbDev->width, fbDev->height, strerror(-err)); + + err = grDev->alloc(grDev, + fbDev->width, fbDev->height, fbDev->format, + GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride); + + LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s", + fbDev->width, fbDev->height, strerror(-err)); + } + + uint32_t flags = fbDev->flags & SURFACE_FLAG_MAPPED; + + /* + * FIXME: SURFACE_FLAG_PRESERVE_CONTENT + * how to implement this, there is no concept of preserve content in + * the framebuffer, which just "posts" buffer. + * + * It looks like what we need is a way to know if the posted buffer can + * be reused. But if so, why allocating 2 buffers?... + * + * should the lock/unlock calls take care of the copy-back? + * + * + * In the end, the client wants to know if the backbuffer is preserved + * though... it's complicated. + * + */ + + //flags |= SURFACE_FLAG_PRESERVE_CONTENT; + + + const_cast(android_native_window_t::flags) = flags; + const_cast(android_native_window_t::xdpi) = fbDev->xdpi; + const_cast(android_native_window_t::ydpi) = fbDev->ydpi; + const_cast(android_native_window_t::minSwapInterval) = + fbDev->minSwapInterval; + const_cast(android_native_window_t::maxSwapInterval) = + fbDev->maxSwapInterval; + + android_native_window_t::setSwapInterval = setSwapInterval; + android_native_window_t::dequeueBuffer = dequeueBuffer; + android_native_window_t::lockBuffer = lockBuffer; + android_native_window_t::queueBuffer = queueBuffer; +} + +FramebufferNativeWindow::~FramebufferNativeWindow() { + grDev->free(grDev, buffers[0]->handle); + grDev->free(grDev, buffers[1]->handle); + gralloc_close(grDev); + framebuffer_close(fbDev); +} + +void FramebufferNativeWindow::connect(android_native_window_t* window) +{ +} + +void FramebufferNativeWindow::disconnect(android_native_window_t* window) +{ +} + +int FramebufferNativeWindow::setSwapInterval( + android_native_window_t* window, int interval) +{ + framebuffer_device_t* fb = getSelf(window)->fbDev; + return fb->setSwapInterval(fb, interval); +} + +void FramebufferNativeWindow::setSwapRectangle(const Rect& dirty) +{ + Mutex::Autolock _l(mutex); + mDirty = dirty; +} + +int FramebufferNativeWindow::dequeueBuffer(android_native_window_t* window, + android_native_buffer_t** buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; + + // wait for a free buffer + while (!self->mNumFreeBuffers) { + self->mCondition.wait(self->mutex); + } + // get this buffer + self->mNumFreeBuffers--; + int index = self->mBufferHead++; + if (self->mBufferHead >= self->mNumBuffers) + self->mBufferHead = 0; + + *buffer = self->buffers[index].get(); + + return 0; +} + +int FramebufferNativeWindow::lockBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + + // wait that the buffer we're locking is not front anymore + while (self->front == buffer) { + self->mCondition.wait(self->mutex); + } + + return NO_ERROR; +} + +int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, + android_native_buffer_t* buffer) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; + buffer_handle_t handle = static_cast(buffer)->handle; + int res = fb->post(fb, handle); + self->front = static_cast(buffer); + self->mNumFreeBuffers++; + self->mCondition.broadcast(); + return res; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + + +EGLNativeWindowType android_createDisplaySurface(void) +{ + return new android::FramebufferNativeWindow(); +} + diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 26e694a70ad5..30da911fc72c 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -88,6 +88,13 @@ void Region::set(const Rect& r) mRegion.setRect(ir); } +void Region::set(uint32_t w, uint32_t h) +{ + SkIRect ir; + ir.set(0, 0, w, h); + mRegion.setRect(ir); +} + // ---------------------------------------------------------------------------- Region& Region::orSelf(const Rect& r) diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index fb105b346c7e..68fd9632cc12 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -53,7 +52,7 @@ namespace android { ANDROID_SINGLETON_STATIC_INSTANCE( SurfaceBuffer ) SurfaceBuffer::SurfaceBuffer() - : BASE(), handle(0), mOwner(false) + : BASE(), handle(0), mOwner(false), mBufferMapper(BufferMapper::get()) { width = height = @@ -64,7 +63,7 @@ SurfaceBuffer::SurfaceBuffer() } SurfaceBuffer::SurfaceBuffer(const Parcel& data) - : BASE(), handle(0), mOwner(true) + : BASE(), handle(0), mOwner(true), mBufferMapper(BufferMapper::get()) { // we own the handle in this case width = data.readInt32(); @@ -91,6 +90,26 @@ int SurfaceBuffer::getHandle(android_native_buffer_t const * base, return 0; } +status_t SurfaceBuffer::lock(uint32_t usage) +{ + const Rect lockBounds(width, height); + status_t res = lock(usage, lockBounds); + return res; +} + +status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect) +{ + status_t res = getBufferMapper().lock(handle, usage, rect, &bits); + return res; +} + +status_t SurfaceBuffer::unlock() +{ + status_t res = getBufferMapper().unlock(handle); + bits = NULL; + return res; +} + status_t SurfaceBuffer::writeToParcel(Parcel* reply, android_native_buffer_t const* buffer) { @@ -110,9 +129,17 @@ status_t SurfaceBuffer::writeToParcel(Parcel* reply, // ---------------------------------------------------------------------- -static void copyBlt(const android_native_buffer_t* dst, - const android_native_buffer_t* src, const Region& reg) +static void copyBlt( + const sp& dst, + const sp& src, + const Region& reg) { + src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds()); + uint8_t const * const src_bits = (uint8_t const *)src->bits; + + dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds()); + uint8_t* const dst_bits = (uint8_t*)dst->bits; + Region::iterator iterator(reg); if (iterator) { // NOTE: dst and src must be the same format @@ -120,29 +147,29 @@ static void copyBlt(const android_native_buffer_t* dst, const size_t bpp = bytesPerPixel(src->format); const size_t dbpr = dst->stride * bpp; const size_t sbpr = src->stride * bpp; + while (iterator.iterate(&r)) { - ssize_t h = r.bottom - r.top; - if (h) { - size_t size = (r.right - r.left) * bpp; - uint8_t* s = (GGLubyte*)src->bits + - (r.left + src->stride * r.top) * bpp; - uint8_t* d = (GGLubyte*)dst->bits + - (r.left + dst->stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; - } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); + ssize_t h = r.height(); + if (h <= 0) continue; + size_t size = r.width() * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); } } + + src->unlock(); + dst->unlock(); } - // ============================================================================ // SurfaceControl // ============================================================================ @@ -347,12 +374,14 @@ sp SurfaceControl::getSurface() const Surface::Surface(const sp& surface) : mClient(surface->mClient), mSurface(surface->mSurface), mToken(surface->mToken), mIdentity(surface->mIdentity), - mFormat(surface->mFormat), mFlags(surface->mFlags) + mFormat(surface->mFormat), mFlags(surface->mFlags), + mBufferMapper(BufferMapper::get()) { init(); } Surface::Surface(const Parcel& parcel) + : mBufferMapper(BufferMapper::get()) { sp clientBinder = parcel.readStrongBinder(); mSurface = interface_cast(parcel.readStrongBinder()); @@ -369,16 +398,11 @@ Surface::Surface(const Parcel& parcel) void Surface::init() { - android_native_window_t::connect = connect; - android_native_window_t::disconnect = disconnect; android_native_window_t::setSwapInterval = setSwapInterval; - android_native_window_t::setSwapRectangle = setSwapRectangle; android_native_window_t::dequeueBuffer = dequeueBuffer; android_native_window_t::lockBuffer = lockBuffer; android_native_window_t::queueBuffer = queueBuffer; - mSwapRectangle.makeInvalid(); - DisplayInfo dinfo; SurfaceComposerClient::getDisplayInfo(0, &dinfo); const_cast(android_native_window_t::xdpi) = dinfo.xdpi; @@ -396,7 +420,7 @@ Surface::~Surface() // its buffers in this process. for (int i=0 ; i<2 ; i++) { if (mBuffers[i] != 0) { - BufferMapper::get().unmap(mBuffers[i]->getHandle(), this); + getBufferMapper().unregisterBuffer(mBuffers[i]->getHandle()); } } @@ -443,22 +467,6 @@ bool Surface::isSameSurface( // ---------------------------------------------------------------------------- -int Surface::setSwapRectangle(android_native_window_t* window, - int l, int t, int w, int h) -{ - Surface* self = getSelf(window); - self->setSwapRectangle(Rect(l, t, l+w, t+h)); - return 0; -} - -void Surface::connect(android_native_window_t* window) -{ -} - -void Surface::disconnect(android_native_window_t* window) -{ -} - int Surface::setSwapInterval(android_native_window_t* window, int interval) { return 0; @@ -487,6 +495,26 @@ int Surface::queueBuffer(android_native_window_t* window, // ---------------------------------------------------------------------------- +status_t Surface::dequeueBuffer(sp* buffer) +{ + android_native_buffer_t* out; + status_t err = dequeueBuffer(&out); + *buffer = SurfaceBuffer::getSelf(out); + return err; +} + +status_t Surface::lockBuffer(const sp& buffer) +{ + return lockBuffer(buffer.get()); +} + +status_t Surface::queueBuffer(const sp& buffer) +{ + return queueBuffer(buffer.get()); +} + +// ---------------------------------------------------------------------------- + int Surface::dequeueBuffer(android_native_buffer_t** buffer) { // FIXME: dequeueBuffer() needs proper implementation @@ -515,8 +543,9 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) } const sp& backBuffer(mBuffers[backIdx]); + mDirtyRegion.set(backBuffer->width, backBuffer->height); *buffer = backBuffer.get(); - + return NO_ERROR; } @@ -542,11 +571,14 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) if (err != NO_ERROR) return err; + if (mSwapRectangle.isValid()) { + mDirtyRegion.set(mSwapRectangle); + } + // transmit the dirty region - const Region dirty(swapRectangle()); SurfaceID index(mToken); layer_cblk_t* const lcblk = &(cblk->layers[index]); - _send_dirty_region(lcblk, dirty); + _send_dirty_region(lcblk, mDirtyRegion); uint32_t newstate = cblk->unlock_layer_and_post(size_t(index)); if (!(newstate & eNextFlipPending)) @@ -561,27 +593,20 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) { return Surface::lock(info, NULL, blocking); } -status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking) +status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) { // FIXME: needs some locking here - android_native_buffer_t* backBuffer; + + sp backBuffer; status_t err = dequeueBuffer(&backBuffer); if (err == NO_ERROR) { err = lockBuffer(backBuffer); if (err == NO_ERROR) { - backBuffer->common.incRef(&backBuffer->common); - mLockedBuffer = backBuffer; - other->w = backBuffer->width; - other->h = backBuffer->height; - other->s = backBuffer->stride; - other->usage = backBuffer->usage; - other->format = backBuffer->format; - other->bits = backBuffer->bits; - // we handle copy-back here... const Rect bounds(backBuffer->width, backBuffer->height); - Region newDirtyRegion; + Region scratch(bounds); + Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch); per_client_cblk_t* const cblk = mClient->mControl; layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]); @@ -590,43 +615,34 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking) // content is meaningless in this case and the whole surface // needs to be redrawn. newDirtyRegion.set(bounds); - if (dirty) { - *dirty = newDirtyRegion; - } - } else - { - if (dirty) { - dirty->andSelf(Region(bounds)); - newDirtyRegion = *dirty; - } else { - newDirtyRegion.set(bounds); - } - Region copyback; + } else { + newDirtyRegion.andSelf(bounds); if (!(lcblk->flags & eNoCopyBack)) { - const Region previousDirtyRegion(dirtyRegion()); - copyback = previousDirtyRegion.subtract(newDirtyRegion); - } - const sp& frontBuffer(mBuffers[1-mBackbufferIndex]); - if (!copyback.isEmpty() && frontBuffer!=0) { - // copy front to back - copyBlt(backBuffer, frontBuffer.get(), copyback); + const sp& frontBuffer(mBuffers[1-mBackbufferIndex]); + const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); + if (!copyback.isEmpty() && frontBuffer!=0) { + // copy front to back + copyBlt(backBuffer, frontBuffer, copyback); + } } } - setDirtyRegion(newDirtyRegion); - + mDirtyRegion = newDirtyRegion; + mOldDirtyRegion = newDirtyRegion; - Rect lockBounds(backBuffer->width, backBuffer->height); - if (dirty) { - lockBounds = dirty->bounds(); - } - buffer_handle_t handle; - backBuffer->getHandle(backBuffer, &handle); - status_t res = BufferMapper::get().lock(handle, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - lockBounds); + status_t res = backBuffer->lock( + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + newDirtyRegion.bounds()); + LOGW_IF(res, "failed locking buffer %d (%p)", - mBackbufferIndex, handle); - setSwapRectangle(lockBounds); + mBackbufferIndex, backBuffer->handle); + + mLockedBuffer = backBuffer; + other->w = backBuffer->width; + other->h = backBuffer->height; + other->s = backBuffer->stride; + other->usage = backBuffer->usage; + other->format = backBuffer->format; + other->bits = backBuffer->bits; } } return err; @@ -639,16 +655,12 @@ status_t Surface::unlockAndPost() if (mLockedBuffer == 0) return BAD_VALUE; - buffer_handle_t handle; - mLockedBuffer->getHandle(mLockedBuffer, &handle); - status_t res = BufferMapper::get().unlock(handle); + status_t res = mLockedBuffer->unlock(); LOGW_IF(res, "failed unlocking buffer %d (%p)", - mBackbufferIndex, handle); - - const Rect dirty(dirtyRegion().bounds()); - setSwapRectangle(dirty); + mBackbufferIndex, mLockedBuffer->handle); + status_t err = queueBuffer(mLockedBuffer); - mLockedBuffer->common.decRef(&mLockedBuffer->common); + mLockedBuffer->bits = NULL; mLockedBuffer = 0; return err; } @@ -666,15 +678,6 @@ void Surface::_send_dirty_region( } } -Region Surface::dirtyRegion() const { - return mDirtyRegion; -} -void Surface::setDirtyRegion(const Region& region) const { - mDirtyRegion = region; -} -const Rect& Surface::swapRectangle() const { - return mSwapRectangle; -} void Surface::setSwapRectangle(const Rect& r) { mSwapRectangle = r; } @@ -687,10 +690,10 @@ status_t Surface::getBufferLocked(int index) if (buffer != 0) { sp& currentBuffer(mBuffers[index]); if (currentBuffer != 0) { - BufferMapper::get().unmap(currentBuffer->getHandle(), this); + getBufferMapper().unregisterBuffer(currentBuffer->getHandle()); currentBuffer.clear(); } - err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits, this); + err = getBufferMapper().registerBuffer(buffer->getHandle()); LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); if (err == NO_ERROR) { currentBuffer = buffer; diff --git a/opengl/include/EGL/android_natives.h b/opengl/include/EGL/android_natives.h index e3c3b86e49f4..329705b65a8c 100644 --- a/opengl/include/EGL/android_natives.h +++ b/opengl/include/EGL/android_natives.h @@ -96,18 +96,6 @@ struct android_native_window_t /* Some storage reserved for the OEM's driver. */ intptr_t oem[4]; - /* - * hook called by EGL when the native surface is made current - * (eglMakeCurrent()). This hook can be NULL. - */ - void (*connect)(struct android_native_window_t* window); - - /* - * hook called by EGL when the native surface in not current any-longer. - * This hook can be NULL. - */ - void (*disconnect)(struct android_native_window_t* window); - /* * Set the swap interval for this surface. @@ -117,20 +105,10 @@ struct android_native_window_t int (*setSwapInterval)(struct android_native_window_t* window, int interval); - - /* - * FIXME: needs documentation for setSwapRectangle - * tentative: rect used during queueBuffer to indicate which part of - * the screen needs updating. - */ - int (*setSwapRectangle)(struct android_native_window_t* window, - int left, int top, int width, int height); - - /* * hook called by EGL to acquire a buffer. After this call, the buffer * is not locked, so its content cannot be modified. - * this call may block if no buffers are availlable. + * this call may block if no buffers are available. * * Returns 0 on success or -errno on error. */ @@ -179,7 +157,7 @@ struct android_native_buffer_t int stride; int format; int usage; - void* bits; // non-zero if buffer is mmaped + void* bits; // non-zero if buffer is locked for sw usage void* reserved[2]; diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp index f927de95ecae..9eb99f0bc231 100644 --- a/opengl/libagl/TextureObjectManager.cpp +++ b/opengl/libagl/TextureObjectManager.cpp @@ -23,7 +23,7 @@ namespace android { // ---------------------------------------------------------------------------- EGLTextureObject::EGLTextureObject() - : mCount(0), mSize(0) + : mSize(0) { init(); } @@ -56,6 +56,7 @@ void EGLTextureObject::init() #ifdef LIBAGL_USE_GRALLOC_COPYBITS copybits_fd = -1; #endif // LIBAGL_USE_GRALLOC_COPYBITS + buffer = 0; } void EGLTextureObject::copyParameters(const sp& old) @@ -126,6 +127,7 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s) } surface = *s; internalformat = 0; + buffer = 0; // we should keep the crop_rect, but it's delicate because // the new size of the surface could make it invalid. @@ -144,6 +146,20 @@ status_t EGLTextureObject::setSurface(GGLSurface const* s) return NO_ERROR; } +status_t EGLTextureObject::setImage(android_native_buffer_t* native_buffer) +{ + GGLSurface sur; + sur.version = sizeof(GGLSurface); + sur.width = native_buffer->width; + sur.height= native_buffer->height; + sur.stride= native_buffer->stride; + sur.format= native_buffer->format; + sur.data = 0; + setSurface(&sur); + buffer = native_buffer; + return NO_ERROR; +} + status_t EGLTextureObject::reallocate( GLint level, int w, int h, int s, int format, int compressedFormat, int bpr) @@ -227,7 +243,7 @@ status_t EGLTextureObject::reallocate( // ---------------------------------------------------------------------------- EGLSurfaceManager::EGLSurfaceManager() - : TokenManager(), mCount(0) + : TokenManager() { } diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h index 497528c76b0e..29d50370eb41 100644 --- a/opengl/libagl/TextureObjectManager.h +++ b/opengl/libagl/TextureObjectManager.h @@ -30,6 +30,7 @@ #include #include +#include #include "Tokenizer.h" #include "TokenManager.h" @@ -39,22 +40,20 @@ namespace android { // ---------------------------------------------------------------------------- -class EGLTextureObject +class EGLTextureObject : public LightRefBase { public: EGLTextureObject(); ~EGLTextureObject(); - // protocol for sp<> - inline void incStrong(const void* id) const; - inline void decStrong(const void* id) const; - inline uint32_t getStrongCount() const; + status_t setSurface(GGLSurface const* s); + status_t setImage(android_native_buffer_t* buffer); + void setImageBits(void* vaddr) { surface.data = (GGLubyte*)vaddr; } - status_t setSurface(GGLSurface const* s); status_t reallocate(GLint level, int w, int h, int s, int format, int compressedFormat, int bpr); - inline size_t size() const; + inline size_t size() const { return mSize; } const GGLSurface& mip(int lod) const; GGLSurface& editMip(int lod); bool hasMipmaps() const { return mMipmaps!=0; } @@ -65,7 +64,6 @@ private: status_t allocateMipmaps(); void freeMipmaps(); void init(); - mutable int32_t mCount; size_t mSize; GGLSurface *mMipmaps; int mNumExtraLod; @@ -84,36 +82,19 @@ public: #ifdef LIBAGL_USE_GRALLOC_COPYBITS int copybits_fd; #endif // LIBAGL_USE_GRALLOC_COPYBITS + android_native_buffer_t* buffer; }; -void EGLTextureObject::incStrong(const void* id) const { - android_atomic_inc(&mCount); -} -void EGLTextureObject::decStrong(const void* id) const { - if (android_atomic_dec(&mCount) == 1) { - delete this; - } -} -uint32_t EGLTextureObject::getStrongCount() const { - return mCount; -} -size_t EGLTextureObject::size() const { - return mSize; -} - // ---------------------------------------------------------------------------- -class EGLSurfaceManager : public TokenManager +class EGLSurfaceManager : + public LightRefBase, + public TokenManager { public: EGLSurfaceManager(); ~EGLSurfaceManager(); - // protocol for sp<> - inline void incStrong(const void* id) const; - inline void decStrong(const void* id) const; - typedef void weakref_type; - sp createTexture(GLuint name); sp removeTexture(GLuint name); sp replaceTexture(GLuint name); @@ -121,21 +102,10 @@ public: sp texture(GLuint name); private: - mutable int32_t mCount; mutable Mutex mLock; KeyedVector< GLuint, sp > mTextures; }; -void EGLSurfaceManager::incStrong(const void* id) const { - android_atomic_inc(&mCount); -} -void EGLSurfaceManager::decStrong(const void* id) const { - if (android_atomic_dec(&mCount) == 1) { - delete this; - } -} - - // ---------------------------------------------------------------------------- }; // namespace android diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index eefe614c2fb7..6d2cc9111c84 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -1371,9 +1371,18 @@ void glDrawArrays(GLenum mode, GLint first, GLsizei count) if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK)) return; // all triangles are culled + validate_arrays(c, mode); + + const uint32_t enables = c->rasterizer.state.enables; + if (enables & GGL_ENABLE_TMUS) + ogles_lock_textures(c); + drawArraysPrims[mode](c, first, count); + if (enables & GGL_ENABLE_TMUS) + ogles_unlock_textures(c); + #if VC_CACHE_STATISTICS c->vc.total = count; c->vc.dump_stats(mode); @@ -1425,8 +1434,16 @@ void glDrawElements( indices = c->arrays.element_array_buffer->data + uintptr_t(indices); } + const uint32_t enables = c->rasterizer.state.enables; + if (enables & GGL_ENABLE_TMUS) + ogles_lock_textures(c); + drawElementsPrims[mode](c, count, indices); + + if (enables & GGL_ENABLE_TMUS) + ogles_unlock_textures(c); + #if VC_CACHE_STATISTICS c->vc.total = count; c->vc.dump_stats(mode); diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 9384e18dad1d..04ca431778c2 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -212,8 +212,11 @@ struct egl_window_surface_v2_t : public egl_surface_t virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; private: + status_t lock(android_native_buffer_t* buf, int usage); + status_t unlock(android_native_buffer_t* buf); android_native_window_t* nativeWindow; android_native_buffer_t* buffer; + gralloc_module_t const* module; int width; int height; }; @@ -222,8 +225,13 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat, android_native_window_t* window) - : egl_surface_t(dpy, config, depthFormat), nativeWindow(window), buffer(0) + : egl_surface_t(dpy, config, depthFormat), + nativeWindow(window), buffer(0), module(0) { + hw_module_t const* pModule; + hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); + module = reinterpret_cast(pModule); + nativeWindow->common.incRef(&nativeWindow->common); nativeWindow->dequeueBuffer(nativeWindow, &buffer); @@ -246,13 +254,44 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, buffer->common.incRef(&buffer->common); nativeWindow->lockBuffer(nativeWindow, buffer); - // FIXME: we need to gralloc lock the buffer + // Lock the buffer + lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + // FIXME: we need to handle the copy-back if needed, but // for now we're a "non preserving" implementation. } +status_t egl_window_surface_v2_t::lock( + android_native_buffer_t* buf, int usage) +{ + int err; + buffer_handle_t bufferHandle; + err = buf->getHandle(buf, &bufferHandle); + if (err < 0) + return err; + + err = module->lock(module, bufferHandle, + usage, 0, 0, buf->width, buf->height, &buf->bits); + return err; +} + +status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) +{ + int err; + buffer_handle_t bufferHandle; + err = buf->getHandle(buf, &bufferHandle); + if (err < 0) + return err; + + err = module->unlock(module, bufferHandle); + buf->bits = NULL; + return err; +} + + egl_window_surface_v2_t::~egl_window_surface_v2_t() { if (buffer) { + unlock(buffer); buffer->common.decRef(&buffer->common); } nativeWindow->common.decRef(&nativeWindow->common); @@ -269,6 +308,7 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers() //mDisplaySurface->copyFrontToBack(copyback); + unlock(buffer); nativeWindow->queueBuffer(nativeWindow, buffer); buffer->common.decRef(&buffer->common); buffer = 0; @@ -278,6 +318,7 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers() // TODO: lockBuffer should rather be executed when the very first // direct rendering occurs. nativeWindow->lockBuffer(nativeWindow, buffer); + lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); if ((width != buffer->width) || (height != buffer->height)) { @@ -1690,20 +1731,6 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, if (native_buffer->common.version != sizeof(android_native_buffer_t)) return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - - hw_module_t const* pModule; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - buffer_handle_t bufferHandle; - gralloc_module_t const* module = - reinterpret_cast(pModule); - if (native_buffer->getHandle(native_buffer, &bufferHandle) < 0) - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - int err = module->map(module, bufferHandle, &native_buffer->bits); - if (err < 0) { - LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); - return setError(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - } native_buffer->common.incRef(&native_buffer->common); return (EGLImageKHR)native_buffer; @@ -1723,18 +1750,6 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) if (native_buffer->common.version != sizeof(android_native_buffer_t)) return setError(EGL_BAD_PARAMETER, EGL_FALSE); - hw_module_t const* pModule; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule) == 0) { - buffer_handle_t bufferHandle; - gralloc_module_t const* module = - reinterpret_cast(pModule); - int err = native_buffer->getHandle(native_buffer, &bufferHandle); - if (err == 0) { - int err = module->unmap(module, bufferHandle); - LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err)); - } - } - native_buffer->common.decRef(&native_buffer->common); return EGL_TRUE; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index 9dca1338c2fb..f2d8da3ca259 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -103,7 +103,7 @@ void validate_tmu(ogles_context_t* c, int i) } } -void ogles_validate_texture_impl(ogles_context_t* c) +void ogles_validate_texture(ogles_context_t* c) { for (int i=0 ; irasterizer.state.texture[i].enable) @@ -117,6 +117,67 @@ void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) { c->textures.tmu[tmu].dirty = flags; } +/* + * If the active textures are EGLImage, they need to be locked before + * they can be used. + * + * FIXME: code below is far from being optimal + * + */ + +void ogles_lock_textures(ogles_context_t* c) +{ + for (int i=0 ; irasterizer.state.texture[i].enable) { + texture_unit_t& u(c->textures.tmu[i]); + android_native_buffer_t* native_buffer = u.texture->buffer; + if (native_buffer) { + c->rasterizer.procs.activeTexture(c, i); + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) + continue; + + gralloc_module_t const* module = + reinterpret_cast(pModule); + buffer_handle_t bufferHandle; + native_buffer->getHandle(native_buffer, &bufferHandle); + int err = module->lock(module, bufferHandle, + GRALLOC_USAGE_SW_READ_OFTEN, + 0, 0, native_buffer->width, native_buffer->height, + &native_buffer->bits); + + u.texture->setImageBits(native_buffer->bits); + c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); + } + } + } +} + +void ogles_unlock_textures(ogles_context_t* c) +{ + for (int i=0 ; irasterizer.state.texture[i].enable) { + texture_unit_t& u(c->textures.tmu[i]); + android_native_buffer_t* native_buffer = u.texture->buffer; + if (native_buffer) { + c->rasterizer.procs.activeTexture(c, i); + hw_module_t const* pModule; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) + continue; + + gralloc_module_t const* module = + reinterpret_cast(pModule); + buffer_handle_t bufferHandle; + native_buffer->getHandle(native_buffer, &bufferHandle); + module->unlock(module, bufferHandle); + u.texture->setImageBits(NULL); + c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); + } + } + } + c->rasterizer.procs.activeTexture(c, c->textures.active); +} + // ---------------------------------------------------------------------------- #if 0 #pragma mark - @@ -592,6 +653,8 @@ invalid_enum: static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, ogles_context_t* c) { + ogles_lock_textures(c); + const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = gglIntToFixed(cbSurface.height) - (y + h); w >>= FIXED_BITS; @@ -650,6 +713,8 @@ static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h gglFixedToIntRound(y), gglFixedToIntRound(x)+w, gglFixedToIntRound(y)+h); + + ogles_unlock_textures(c); } static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, @@ -724,6 +789,8 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte goto slow_case; } + ogles_lock_textures(c); + c->rasterizer.procs.texCoord2i(c, s0, t0); const uint32_t enables = c->rasterizer.state.enables; if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) @@ -734,6 +801,9 @@ static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_conte c->rasterizer.procs.disable(c, GGL_AA); c->rasterizer.procs.shadeModel(c, GL_FLAT); c->rasterizer.procs.recti(c, x, y, x+w, y+h); + + ogles_unlock_textures(c); + return; } } @@ -1460,23 +1530,9 @@ void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) return; } - if (native_buffer->bits == NULL) { - // this buffer cannot be used with this implementation - ogles_error(c, GL_INVALID_VALUE); - return; - } - - GGLSurface sur; - sur.version = sizeof(GGLSurface); - sur.width = native_buffer->width; - sur.height= native_buffer->height; - sur.stride= native_buffer->stride; - sur.format= native_buffer->format; - sur.data = (GGLubyte*)native_buffer->bits; - // bind it to the texture unit sp tex = getAndBindActiveTextureObject(c); - tex->setSurface(&sur); + tex->setImage(native_buffer); /* * Here an implementation can retrieve the buffer_handle_t of this buffer diff --git a/opengl/libagl/texture.h b/opengl/libagl/texture.h index 5c57948c92d5..98f75509db22 100644 --- a/opengl/libagl/texture.h +++ b/opengl/libagl/texture.h @@ -32,13 +32,9 @@ namespace android { void ogles_init_texture(ogles_context_t* c); void ogles_uninit_texture(ogles_context_t* c); -void ogles_validate_texture_impl(ogles_context_t* c); - -inline void ogles_validate_texture(ogles_context_t* c) { - if (c->rasterizer.state.enables & GGL_ENABLE_TMUS) - ogles_validate_texture_impl(c); -} - +void ogles_validate_texture(ogles_context_t* c); +void ogles_lock_textures(ogles_context_t* c); +void ogles_unlock_textures(ogles_context_t* c); }; // namespace android diff --git a/opengl/tests/copybits/Android.mk b/opengl/tests/copybits/Android.mk index d5ded42b5fb1..2876a1eec442 100644 --- a/opengl/tests/copybits/Android.mk +++ b/opengl/tests/copybits/Android.mk @@ -14,5 +14,5 @@ LOCAL_MODULE:= test-opengl-copybits LOCAL_MODULE_TAGS := tests -include $(BUILD_EXECUTABLE) +##include $(BUILD_EXECUTABLE) -- cgit v1.2.3-59-g8ed1b From 430f2ed5c03312700131a70c858b98e1cc6bc161 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 5 May 2009 00:37:46 -0700 Subject: removed the "bits" attribute from android_native_buffer_t. "bits" can never be trusted now that we need to call lock() on the handle to get the virtual address of the buffer. --- include/ui/Surface.h | 4 +- libs/surfaceflinger/LayerBitmap.cpp | 5 ++- libs/ui/Surface.cpp | 23 +++++----- opengl/include/EGL/android_natives.h | 3 +- opengl/libagl/egl.cpp | 83 +++++++++++++++++++++++------------- opengl/libagl/texture.cpp | 5 ++- 6 files changed, 73 insertions(+), 50 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 6eb06ae65f35..ce507195a733 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -54,8 +54,8 @@ public: return handle; } - status_t lock(uint32_t usage); - status_t lock(uint32_t usage, const Rect& rect); + status_t lock(uint32_t usage, void** vaddr); + status_t lock(uint32_t usage, const Rect& rect, void** vaddr); status_t unlock(); protected: diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index 38d4bcf02f7d..765d90b82ef5 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -116,7 +116,8 @@ status_t Buffer::initSize(uint32_t w, uint32_t h) status_t Buffer::lock(GGLSurface* sur, uint32_t usage) { - status_t res = SurfaceBuffer::lock(usage); + void* vaddr; + status_t res = SurfaceBuffer::lock(usage, &vaddr); if (res == NO_ERROR && sur) { sur->version = sizeof(GGLSurface); sur->width = width; @@ -124,7 +125,7 @@ status_t Buffer::lock(GGLSurface* sur, uint32_t usage) sur->stride = stride; sur->format = format; sur->vstride = mVStride; - sur->data = static_cast(bits); + sur->data = static_cast(vaddr); } return res; } diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 68fd9632cc12..5f2138e8d6ca 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -90,23 +90,22 @@ int SurfaceBuffer::getHandle(android_native_buffer_t const * base, return 0; } -status_t SurfaceBuffer::lock(uint32_t usage) +status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr) { const Rect lockBounds(width, height); - status_t res = lock(usage, lockBounds); + status_t res = lock(usage, lockBounds, vaddr); return res; } -status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect) +status_t SurfaceBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr) { - status_t res = getBufferMapper().lock(handle, usage, rect, &bits); + status_t res = getBufferMapper().lock(handle, usage, rect, vaddr); return res; } status_t SurfaceBuffer::unlock() { status_t res = getBufferMapper().unlock(handle); - bits = NULL; return res; } @@ -134,11 +133,11 @@ static void copyBlt( const sp& src, const Region& reg) { - src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds()); - uint8_t const * const src_bits = (uint8_t const *)src->bits; + uint8_t const * src_bits; + src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(), (void**)&src_bits); - dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds()); - uint8_t* const dst_bits = (uint8_t*)dst->bits; + uint8_t* dst_bits; + dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(), (void**)&dst_bits); Region::iterator iterator(reg); if (iterator) { @@ -629,9 +628,10 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) mDirtyRegion = newDirtyRegion; mOldDirtyRegion = newDirtyRegion; + void* vaddr; status_t res = backBuffer->lock( GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - newDirtyRegion.bounds()); + newDirtyRegion.bounds(), &vaddr); LOGW_IF(res, "failed locking buffer %d (%p)", mBackbufferIndex, backBuffer->handle); @@ -642,7 +642,7 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) other->s = backBuffer->stride; other->usage = backBuffer->usage; other->format = backBuffer->format; - other->bits = backBuffer->bits; + other->bits = vaddr; } } return err; @@ -660,7 +660,6 @@ status_t Surface::unlockAndPost() mBackbufferIndex, mLockedBuffer->handle); status_t err = queueBuffer(mLockedBuffer); - mLockedBuffer->bits = NULL; mLockedBuffer = 0; return err; } diff --git a/opengl/include/EGL/android_natives.h b/opengl/include/EGL/android_natives.h index 329705b65a8c..8db2bb3f1cd6 100644 --- a/opengl/include/EGL/android_natives.h +++ b/opengl/include/EGL/android_natives.h @@ -157,9 +157,8 @@ struct android_native_buffer_t int stride; int format; int usage; - void* bits; // non-zero if buffer is locked for sw usage - void* reserved[2]; + void* reserved[3]; int (*getHandle)(struct android_native_buffer_t const * base, buffer_handle_t* handle); diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 04ca431778c2..67dfd3eada65 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -146,9 +146,10 @@ struct egl_surface_t virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0; virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0; + virtual void connect() {} + virtual void disconnect() {} virtual EGLint getWidth() const = 0; virtual EGLint getHeight() const = 0; - virtual void* getBits() const = 0; virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; @@ -204,21 +205,24 @@ struct egl_window_surface_v2_t : public egl_surface_t virtual EGLBoolean swapBuffers(); virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); + virtual void connect(); + virtual void disconnect(); virtual EGLint getWidth() const { return buffer->width; } virtual EGLint getHeight() const { return buffer->height; } - virtual void* getBits() const; virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; + private: - status_t lock(android_native_buffer_t* buf, int usage); + status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); status_t unlock(android_native_buffer_t* buf); android_native_window_t* nativeWindow; android_native_buffer_t* buffer; gralloc_module_t const* module; int width; int height; + void* bits; }; egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, @@ -226,7 +230,7 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, int32_t depthFormat, android_native_window_t* window) : egl_surface_t(dpy, config, depthFormat), - nativeWindow(window), buffer(0), module(0) + nativeWindow(window), buffer(0), module(0), bits(NULL) { hw_module_t const* pModule; hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); @@ -249,20 +253,26 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, } } - // TODO: lockBuffer should rather be executed when the very first - // direct rendering occurs. buffer->common.incRef(&buffer->common); - nativeWindow->lockBuffer(nativeWindow, buffer); +} +void egl_window_surface_v2_t::connect() +{ // Lock the buffer - lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - - // FIXME: we need to handle the copy-back if needed, but - // for now we're a "non preserving" implementation. + nativeWindow->lockBuffer(nativeWindow, buffer); + lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits); +} + +void egl_window_surface_v2_t::disconnect() +{ + if (buffer) { + bits = NULL; + unlock(buffer); + } } status_t egl_window_surface_v2_t::lock( - android_native_buffer_t* buf, int usage) + android_native_buffer_t* buf, int usage, void** vaddr) { int err; buffer_handle_t bufferHandle; @@ -271,7 +281,7 @@ status_t egl_window_surface_v2_t::lock( return err; err = module->lock(module, bufferHandle, - usage, 0, 0, buf->width, buf->height, &buf->bits); + usage, 0, 0, buf->width, buf->height, vaddr); return err; } @@ -284,14 +294,12 @@ status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) return err; err = module->unlock(module, bufferHandle); - buf->bits = NULL; return err; } egl_window_surface_v2_t::~egl_window_surface_v2_t() { if (buffer) { - unlock(buffer); buffer->common.decRef(&buffer->common); } nativeWindow->common.decRef(&nativeWindow->common); @@ -317,9 +325,9 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers() // TODO: lockBuffer should rather be executed when the very first // direct rendering occurs. + void* vaddr; nativeWindow->lockBuffer(nativeWindow, buffer); - lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - + lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits); if ((width != buffer->width) || (height != buffer->height)) { // TODO: we probably should reset the swap rect here @@ -363,7 +371,7 @@ EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) buffer.width = this->buffer->width; buffer.height = this->buffer->height; buffer.stride = this->buffer->stride; - buffer.data = (GGLubyte*)this->buffer->bits; + buffer.data = (GGLubyte*)bits; buffer.format = this->buffer->format; gl->rasterizer.procs.colorBuffer(gl, &buffer); if (depth.data != gl->rasterizer.state.buffers.depth.data) @@ -392,14 +400,11 @@ EGLBoolean egl_window_surface_v2_t::bindReadSurface(ogles_context_t* gl) buffer.width = this->buffer->width; buffer.height = this->buffer->height; buffer.stride = this->buffer->stride; - buffer.data = (GGLubyte*)this->buffer->bits; + buffer.data = (GGLubyte*)bits; // FIXME: hopefully is is LOCKED!!! buffer.format = this->buffer->format; gl->rasterizer.procs.readBuffer(gl, &buffer); return EGL_TRUE; } -void* egl_window_surface_v2_t::getBits() const { - return (GGLubyte*)buffer->bits; -} EGLint egl_window_surface_v2_t::getHorizontalResolution() const { return (nativeWindow->xdpi * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } @@ -434,7 +439,6 @@ struct egl_pixmap_surface_t : public egl_surface_t virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return nativePixmap.width; } virtual EGLint getHeight() const { return nativePixmap.height; } - virtual void* getBits() const { return nativePixmap.data; } private: egl_native_pixmap_t nativePixmap; }; @@ -499,7 +503,6 @@ struct egl_pbuffer_surface_t : public egl_surface_t virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return pbuffer.width; } virtual EGLint getHeight() const { return pbuffer.height; } - virtual void* getBits() const { return pbuffer.data; } private: GGLSurface pbuffer; }; @@ -1311,6 +1314,11 @@ EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface eglSurface) return setError(EGL_BAD_SURFACE, EGL_FALSE); if (surface->dpy != dpy) return setError(EGL_BAD_DISPLAY, EGL_FALSE); + if (surface->ctx) { + // FIXME: this surface is current check what the spec says + surface->disconnect(); + surface->ctx = 0; + } delete surface; } return EGL_TRUE; @@ -1436,21 +1444,28 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, egl_surface_t* r = (egl_surface_t*)read; if ((d && d->ctx && d->ctx != ctx) || (r && r->ctx && r->ctx != ctx)) { - // once of the surface is bound to a context in another thread + // one of the surface is bound to a context in another thread return setError(EGL_BAD_ACCESS, EGL_FALSE); } } - // TODO: call connect / disconnect on the surface - ogles_context_t* gl = (ogles_context_t*)ctx; if (makeCurrent(gl) == 0) { if (ctx) { egl_context_t* c = egl_context_t::context(ctx); egl_surface_t* d = (egl_surface_t*)draw; egl_surface_t* r = (egl_surface_t*)read; - c->read = read; + + if (c->draw) { + reinterpret_cast(c->draw)->disconnect(); + } + if (c->read) { + // FIXME: unlock/disconnect the read surface too + } + c->draw = draw; + c->read = read; + if (c->flags & egl_context_t::NEVER_CURRENT) { c->flags &= ~egl_context_t::NEVER_CURRENT; GLint w = 0; @@ -1464,10 +1479,12 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, ogles_scissor(gl, 0, 0, w, h); } if (d) { + d->connect(); d->ctx = ctx; d->bindDrawSurface(gl); } if (r) { + // FIXME: lock/connect the read surface too r->ctx = ctx; r->bindReadSurface(gl); } @@ -1478,8 +1495,14 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, egl_context_t* c = egl_context_t::context(current_ctx); egl_surface_t* d = (egl_surface_t*)c->draw; egl_surface_t* r = (egl_surface_t*)c->read; - if (d) d->ctx = EGL_NO_CONTEXT; - if (r) r->ctx = EGL_NO_CONTEXT; + if (d) { + d->ctx = EGL_NO_CONTEXT; + d->disconnect(); + } + if (r) { + r->ctx = EGL_NO_CONTEXT; + // FIXME: unlock/disconnect the read surface too + } } } return EGL_TRUE; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index f2d8da3ca259..9bcbfdd24401 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -141,12 +141,13 @@ void ogles_lock_textures(ogles_context_t* c) reinterpret_cast(pModule); buffer_handle_t bufferHandle; native_buffer->getHandle(native_buffer, &bufferHandle); + void* vaddr; int err = module->lock(module, bufferHandle, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, native_buffer->width, native_buffer->height, - &native_buffer->bits); + &vaddr); - u.texture->setImageBits(native_buffer->bits); + u.texture->setImageBits(vaddr); c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); } } -- cgit v1.2.3-59-g8ed1b From e633f9339a2556771c79c784b0b23a9aade30485 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 5 May 2009 00:59:23 -0700 Subject: get rid of android_native_buffer_t::getHandle() and replace it with an handle field this abstraction was not necessary. things are easier now. --- include/ui/FramebufferNativeWindow.h | 7 ------- include/ui/Surface.h | 8 -------- libs/ui/Surface.cpp | 27 +++++++-------------------- opengl/include/EGL/android_natives.h | 9 ++++----- opengl/libagl/egl.cpp | 19 +++---------------- opengl/libagl/texture.cpp | 21 ++++++++------------- 6 files changed, 22 insertions(+), 69 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h index 4b281db84433..0db245af44dd 100644 --- a/include/ui/FramebufferNativeWindow.h +++ b/include/ui/FramebufferNativeWindow.h @@ -50,17 +50,10 @@ public: android_native_buffer_t::height = h; android_native_buffer_t::format = f; android_native_buffer_t::usage = u; - android_native_buffer_t::getHandle = getHandle; } -public: - buffer_handle_t handle; private: friend class LightRefBase; ~NativeBuffer() { }; // this class cannot be overloaded - static int getHandle(android_native_buffer_t const * base, buffer_handle_t* handle) { - *handle = getSelf(base)->handle; - return 0; - } }; // --------------------------------------------------------------------------- diff --git a/include/ui/Surface.h b/include/ui/Surface.h index ce507195a733..e9bb1b3f473d 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -50,10 +50,6 @@ class SurfaceBuffer LightRefBase > { public: - buffer_handle_t getHandle() const { - return handle; - } - status_t lock(uint32_t usage, void** vaddr); status_t lock(uint32_t usage, const Rect& rect, void** vaddr); status_t unlock(); @@ -62,7 +58,6 @@ protected: SurfaceBuffer(); SurfaceBuffer(const Parcel& reply); virtual ~SurfaceBuffer(); - buffer_handle_t handle; bool mOwner; inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } @@ -80,9 +75,6 @@ private: static status_t writeToParcel(Parcel* reply, android_native_buffer_t const* buffer); - static int getHandle(android_native_buffer_t const * base, - buffer_handle_t* handle); - BufferMapper& mBufferMapper; }; diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 5f2138e8d6ca..782eac46beb8 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -52,18 +52,18 @@ namespace android { ANDROID_SINGLETON_STATIC_INSTANCE( SurfaceBuffer ) SurfaceBuffer::SurfaceBuffer() - : BASE(), handle(0), mOwner(false), mBufferMapper(BufferMapper::get()) + : BASE(), mOwner(false), mBufferMapper(BufferMapper::get()) { width = height = stride = format = usage = 0; - android_native_buffer_t::getHandle = getHandle; + handle = NULL; } SurfaceBuffer::SurfaceBuffer(const Parcel& data) - : BASE(), handle(0), mOwner(true), mBufferMapper(BufferMapper::get()) + : BASE(), mOwner(true), mBufferMapper(BufferMapper::get()) { // we own the handle in this case width = data.readInt32(); @@ -72,7 +72,6 @@ SurfaceBuffer::SurfaceBuffer(const Parcel& data) format = data.readInt32(); usage = data.readInt32(); handle = data.readNativeHandle(); - android_native_buffer_t::getHandle = getHandle; } SurfaceBuffer::~SurfaceBuffer() @@ -83,13 +82,6 @@ SurfaceBuffer::~SurfaceBuffer() } } -int SurfaceBuffer::getHandle(android_native_buffer_t const * base, - buffer_handle_t* handle) -{ - *handle = getSelf(base)->handle; - return 0; -} - status_t SurfaceBuffer::lock(uint32_t usage, void** vaddr) { const Rect lockBounds(width, height); @@ -112,17 +104,12 @@ status_t SurfaceBuffer::unlock() status_t SurfaceBuffer::writeToParcel(Parcel* reply, android_native_buffer_t const* buffer) { - buffer_handle_t handle; - status_t err = buffer->getHandle(buffer, &handle); - if (err < 0) { - return err; - } reply->writeInt32(buffer->width); reply->writeInt32(buffer->height); reply->writeInt32(buffer->stride); reply->writeInt32(buffer->format); reply->writeInt32(buffer->usage); - reply->writeNativeHandle(handle); + reply->writeNativeHandle(buffer->handle); return NO_ERROR; } @@ -419,7 +406,7 @@ Surface::~Surface() // its buffers in this process. for (int i=0 ; i<2 ; i++) { if (mBuffers[i] != 0) { - getBufferMapper().unregisterBuffer(mBuffers[i]->getHandle()); + getBufferMapper().unregisterBuffer(mBuffers[i]->handle); } } @@ -689,10 +676,10 @@ status_t Surface::getBufferLocked(int index) if (buffer != 0) { sp& currentBuffer(mBuffers[index]); if (currentBuffer != 0) { - getBufferMapper().unregisterBuffer(currentBuffer->getHandle()); + getBufferMapper().unregisterBuffer(currentBuffer->handle); currentBuffer.clear(); } - err = getBufferMapper().registerBuffer(buffer->getHandle()); + err = getBufferMapper().registerBuffer(buffer->handle); LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err)); if (err == NO_ERROR) { currentBuffer = buffer; diff --git a/opengl/include/EGL/android_natives.h b/opengl/include/EGL/android_natives.h index 8db2bb3f1cd6..b8465d580228 100644 --- a/opengl/include/EGL/android_natives.h +++ b/opengl/include/EGL/android_natives.h @@ -157,13 +157,12 @@ struct android_native_buffer_t int stride; int format; int usage; + + void* reserved[2]; - void* reserved[3]; - - int (*getHandle)(struct android_native_buffer_t const * base, - buffer_handle_t* handle); + buffer_handle_t handle; - void* reserved_proc[7]; + void* reserved_proc[8]; }; diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 67dfd3eada65..720ba0bdaff3 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -274,26 +274,14 @@ void egl_window_surface_v2_t::disconnect() status_t egl_window_surface_v2_t::lock( android_native_buffer_t* buf, int usage, void** vaddr) { - int err; - buffer_handle_t bufferHandle; - err = buf->getHandle(buf, &bufferHandle); - if (err < 0) - return err; - - err = module->lock(module, bufferHandle, + int err = module->lock(module, buf->handle, usage, 0, 0, buf->width, buf->height, vaddr); return err; } status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) { - int err; - buffer_handle_t bufferHandle; - err = buf->getHandle(buf, &bufferHandle); - if (err < 0) - return err; - - err = module->unlock(module, bufferHandle); + int err = module->unlock(module, buf->handle); return err; } @@ -379,8 +367,7 @@ EGLBoolean egl_window_surface_v2_t::bindDrawSurface(ogles_context_t* gl) #ifdef LIBAGL_USE_GRALLOC_COPYBITS gl->copybits.drawSurfaceFd = -1; if (supportedCopybitsDestinationFormat(buffer.format)) { - buffer_handle_t handle; - this->buffer->getHandle(this->buffer, &handle); + buffer_handle_t handle = this->buffer->handle; if (handle != NULL) { private_handle_t* hand = private_handle_t::dynamicCast(handle); if (hand != NULL) { diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index 9bcbfdd24401..118964340f48 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -139,10 +139,9 @@ void ogles_lock_textures(ogles_context_t* c) gralloc_module_t const* module = reinterpret_cast(pModule); - buffer_handle_t bufferHandle; - native_buffer->getHandle(native_buffer, &bufferHandle); + void* vaddr; - int err = module->lock(module, bufferHandle, + int err = module->lock(module, native_buffer->handle, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, native_buffer->width, native_buffer->height, &vaddr); @@ -168,9 +167,8 @@ void ogles_unlock_textures(ogles_context_t* c) gralloc_module_t const* module = reinterpret_cast(pModule); - buffer_handle_t bufferHandle; - native_buffer->getHandle(native_buffer, &bufferHandle); - module->unlock(module, bufferHandle); + + module->unlock(module, native_buffer->handle); u.texture->setImageBits(NULL); c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); } @@ -1547,13 +1545,10 @@ void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) */ #ifdef LIBAGL_USE_GRALLOC_COPYBITS tex->copybits_fd = -1; - buffer_handle_t handle; - if (native_buffer->getHandle(native_buffer, &handle) == 0) { - private_handle_t* hand; - if ((hand = private_handle_t::dynamicCast(handle)) != NULL) { - if (hand->usesPhysicallyContiguousMemory()) { - tex->copybits_fd = hand->fd; - } + private_handle_t* hand; + if ((hand = private_handle_t::dynamicCast(native_buffer->handle)) != NULL) { + if (hand->usesPhysicallyContiguousMemory()) { + tex->copybits_fd = hand->fd; } } #endif // LIBAGL_USE_GRALLOC_COPYBITS -- cgit v1.2.3-59-g8ed1b From ac2523b161df2bb507cc88906bb070878266770d Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 5 May 2009 18:11:11 -0700 Subject: move opengl/include/EGL/android_natives.h to include/ui/egl/android_natives.h and don't include it from egl.h the android_native_ types are just forward declared in egl.h --- include/private/ui/SurfaceBuffer.h | 76 +++++++ include/ui/FramebufferNativeWindow.h | 23 +- include/ui/ISurface.h | 2 - include/ui/Surface.h | 40 +--- include/ui/egl/android_natives.h | 240 ++++++++++++++++++++ .../DisplayHardware/DisplayHardware.cpp | 1 - libs/surfaceflinger/LayerBitmap.h | 4 +- libs/ui/BufferMapper.cpp | 2 - libs/ui/FramebufferNativeWindow.cpp | 19 ++ libs/ui/ISurface.cpp | 1 + libs/ui/Surface.cpp | 5 +- opengl/include/EGL/android_natives.h | 241 --------------------- opengl/include/EGL/eglplatform.h | 4 +- opengl/libagl/TextureObjectManager.cpp | 2 + opengl/libagl/TextureObjectManager.h | 2 +- opengl/libagl/egl.cpp | 3 +- opengl/libagl/texture.cpp | 2 +- 17 files changed, 352 insertions(+), 315 deletions(-) create mode 100644 include/private/ui/SurfaceBuffer.h create mode 100644 include/ui/egl/android_natives.h delete mode 100644 opengl/include/EGL/android_natives.h (limited to 'opengl/libagl/egl.cpp') diff --git a/include/private/ui/SurfaceBuffer.h b/include/private/ui/SurfaceBuffer.h new file mode 100644 index 000000000000..a6db50f4cf69 --- /dev/null +++ b/include/private/ui/SurfaceBuffer.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007 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. + */ + +#ifndef ANDROID_UI_PRIVATE_SURFACE_BUFFER_H +#define ANDROID_UI_PRIVATE_SURFACE_BUFFER_H + +#include +#include + +#include + +#include + +namespace android { + +// --------------------------------------------------------------------------- + +class BufferMapper; +class Rect; +class Surface; +class SurfaceBuffer; + +// --------------------------------------------------------------------------- + +class SurfaceBuffer + : public EGLNativeBase< + android_native_buffer_t, + SurfaceBuffer, + LightRefBase > +{ +public: + status_t lock(uint32_t usage, void** vaddr); + status_t lock(uint32_t usage, const Rect& rect, void** vaddr); + status_t unlock(); + +protected: + SurfaceBuffer(); + SurfaceBuffer(const Parcel& reply); + virtual ~SurfaceBuffer(); + bool mOwner; + + inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } + inline BufferMapper& getBufferMapper() { return mBufferMapper; } + +private: + friend class Surface; + friend class BpSurface; + friend class BnSurface; + friend class LightRefBase; + + SurfaceBuffer& operator = (const SurfaceBuffer& rhs); + const SurfaceBuffer& operator = (const SurfaceBuffer& rhs) const; + + static status_t writeToParcel(Parcel* reply, + android_native_buffer_t const* buffer); + + BufferMapper& mBufferMapper; +}; + +}; // namespace android + +#endif // ANDROID_UI_PRIVATE_SURFACE_BUFFER_H + diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h index 0db245af44dd..aad39a2a6b8b 100644 --- a/include/ui/FramebufferNativeWindow.h +++ b/include/ui/FramebufferNativeWindow.h @@ -21,13 +21,14 @@ #include #include -#include #include #include #include +#include + extern "C" EGLNativeWindowType android_createDisplaySurface(void); @@ -36,25 +37,7 @@ namespace android { // --------------------------------------------------------------------------- class Surface; - - -class NativeBuffer - : public EGLNativeBase< - android_native_buffer_t, - NativeBuffer, - LightRefBase > -{ -public: - NativeBuffer(int w, int h, int f, int u) : BASE() { - android_native_buffer_t::width = w; - android_native_buffer_t::height = h; - android_native_buffer_t::format = f; - android_native_buffer_t::usage = u; - } -private: - friend class LightRefBase; - ~NativeBuffer() { }; // this class cannot be overloaded -}; +class NativeBuffer; // --------------------------------------------------------------------------- diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index 1a788720dbcd..e47b75362775 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -20,8 +20,6 @@ #include #include -#include - #include #include #include diff --git a/include/ui/Surface.h b/include/ui/Surface.h index e9bb1b3f473d..8c4f63ddfec0 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -28,7 +28,7 @@ #include #include -#include +#include namespace android { @@ -43,44 +43,6 @@ struct layer_cblk_t; // --------------------------------------------------------------------------- -class SurfaceBuffer - : public EGLNativeBase< - android_native_buffer_t, - SurfaceBuffer, - LightRefBase > -{ -public: - status_t lock(uint32_t usage, void** vaddr); - status_t lock(uint32_t usage, const Rect& rect, void** vaddr); - status_t unlock(); - -protected: - SurfaceBuffer(); - SurfaceBuffer(const Parcel& reply); - virtual ~SurfaceBuffer(); - bool mOwner; - - inline const BufferMapper& getBufferMapper() const { return mBufferMapper; } - inline BufferMapper& getBufferMapper() { return mBufferMapper; } - -private: - friend class Surface; - friend class BpSurface; - friend class BnSurface; - friend class LightRefBase; - - SurfaceBuffer& operator = (const SurfaceBuffer& rhs); - const SurfaceBuffer& operator = (const SurfaceBuffer& rhs) const; - - static status_t writeToParcel(Parcel* reply, - android_native_buffer_t const* buffer); - - BufferMapper& mBufferMapper; -}; - -// --------------------------------------------------------------------------- -class Surface; - class SurfaceControl : public RefBase { public: diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h new file mode 100644 index 000000000000..5842ee72ce7f --- /dev/null +++ b/include/ui/egl/android_natives.h @@ -0,0 +1,240 @@ +/* + * Copyright (C) 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. + */ + +#ifndef ANDROID_ANDROID_NATIVES_H +#define ANDROID_ANDROID_NATIVES_H + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \ + (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d)) + +#define ANDROID_NATIVE_WINDOW_MAGIC \ + ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d') + +#define ANDROID_NATIVE_BUFFER_MAGIC \ + ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r') + +// --------------------------------------------------------------------------- + +struct android_native_buffer_t; + +enum { + /* attributes of this surface or its updater */ + SURFACE_FLAG_PRESERVE_CONTENT = FRAMEBUFFER_RESERVED0, + SURFACE_FLAG_MAPPED = FRAMEBUFFER_FLAG_MAPPED, +}; + +// --------------------------------------------------------------------------- + +struct android_native_base_t +{ + /* a magic value defined by the actual EGL native type */ + int magic; + + /* the sizeof() of the actual EGL native type */ + int version; + + void* reserved[4]; + + /* reference-counting interface */ + void (*incRef)(struct android_native_base_t* base); + void (*decRef)(struct android_native_base_t* base); +}; + + +struct android_native_window_t +{ +#ifdef __cplusplus + android_native_window_t() + : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) + { + common.magic = ANDROID_NATIVE_WINDOW_MAGIC; + common.version = sizeof(android_native_window_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + /* flags describing some attributes of this surface or its updater */ + const uint32_t flags; + + /* min swap interval supported by this updated */ + const int minSwapInterval; + + /* max swap interval supported by this updated */ + const int maxSwapInterval; + + /* horizontal and vertical resolution in DPI */ + const float xdpi; + const float ydpi; + + /* Some storage reserved for the OEM's driver. */ + intptr_t oem[4]; + + + /* + * Set the swap interval for this surface. + * + * Returns 0 on success or -errno on error. + */ + int (*setSwapInterval)(struct android_native_window_t* window, + int interval); + + /* + * hook called by EGL to acquire a buffer. After this call, the buffer + * is not locked, so its content cannot be modified. + * this call may block if no buffers are available. + * + * Returns 0 on success or -errno on error. + */ + int (*dequeueBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t** buffer); + + /* + * hook called by EGL to lock a buffer. This MUST be called before modifying + * the content of a buffer. The buffer must have been acquired with + * dequeueBuffer first. + * + * Returns 0 on success or -errno on error. + */ + int (*lockBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t* buffer); + /* + * hook called by EGL when modifications to the render buffer are done. + * This unlocks and post the buffer. + * + * Buffers MUST be queued in the same order than they were dequeued. + * + * Returns 0 on success or -errno on error. + */ + int (*queueBuffer)(struct android_native_window_t* window, + struct android_native_buffer_t* buffer); + + + void* reserved_proc[5]; +}; + + +struct android_native_buffer_t +{ +#ifdef __cplusplus + android_native_buffer_t() { + common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + common.version = sizeof(android_native_buffer_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + int width; + int height; + int stride; + int format; + int usage; + + void* reserved[2]; + + buffer_handle_t handle; + + void* reserved_proc[8]; +}; + + +/* FIXME: this is legacy for pixmaps */ +struct egl_native_pixmap_t +{ + int32_t version; /* must be 32 */ + int32_t width; + int32_t height; + int32_t stride; + uint8_t* data; + uint8_t format; + uint8_t rfu[3]; + union { + uint32_t compressedFormat; + int32_t vstride; + }; + int32_t reserved; +}; + +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +/*****************************************************************************/ + +#ifdef __cplusplus + +#include + +namespace android { + +/* + * This helper class turns an EGL android_native_xxx type into a C++ + * reference-counted object; with proper type conversions. + */ +template +class EGLNativeBase : public NATIVE_TYPE, public REF +{ +protected: + typedef EGLNativeBase BASE; + EGLNativeBase() : NATIVE_TYPE(), REF() { + NATIVE_TYPE::common.incRef = incRef; + NATIVE_TYPE::common.decRef = decRef; + } + static inline TYPE* getSelf(NATIVE_TYPE* self) { + return static_cast(self); + } + static inline TYPE const* getSelf(NATIVE_TYPE const* self) { + return static_cast(self); + } + static inline TYPE* getSelf(android_native_base_t* base) { + return getSelf(reinterpret_cast(base)); + } + static inline TYPE const * getSelf(android_native_base_t const* base) { + return getSelf(reinterpret_cast(base)); + } + static void incRef(android_native_base_t* base) { + EGLNativeBase* self = getSelf(base); + self->incStrong(self); + } + static void decRef(android_native_base_t* base) { + EGLNativeBase* self = getSelf(base); + self->decStrong(self); + } +}; + +} // namespace android +#endif // __cplusplus + +/*****************************************************************************/ + +#endif /* ANDROID_ANDROID_NATIVES_H */ diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index ca96e140ff7f..374f2e2c8b65 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index 6e136a2ae764..824e0f2b311b 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -28,12 +28,10 @@ #include #include -#include - #include #include - +#include class copybit_image_t; struct android_native_buffer_t; diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp index 1a75c5d9acdf..92a9a86bb0f2 100644 --- a/libs/ui/BufferMapper.cpp +++ b/libs/ui/BufferMapper.cpp @@ -25,8 +25,6 @@ #include #include -#include - #include diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index f235cb44a546..5e69cff985c7 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -42,6 +42,25 @@ namespace android { // ---------------------------------------------------------------------------- +class NativeBuffer + : public EGLNativeBase< + android_native_buffer_t, + NativeBuffer, + LightRefBase > +{ +public: + NativeBuffer(int w, int h, int f, int u) : BASE() { + android_native_buffer_t::width = w; + android_native_buffer_t::height = h; + android_native_buffer_t::format = f; + android_native_buffer_t::usage = u; + } +private: + friend class LightRefBase; + ~NativeBuffer() { }; // this class cannot be overloaded +}; + + /* * This implements the (main) framebuffer management. This class is used * mostly by SurfaceFlinger, but also by command line GL application. diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index fcea8ec70121..ec922d0cf1b2 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -27,6 +27,7 @@ #include #include +#include namespace android { diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index 782eac46beb8..6437619b20e2 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -36,12 +36,11 @@ #include #include -#include +#include #include #include - -#include +#include namespace android { diff --git a/opengl/include/EGL/android_natives.h b/opengl/include/EGL/android_natives.h deleted file mode 100644 index b8465d580228..000000000000 --- a/opengl/include/EGL/android_natives.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 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. - */ - -#ifndef ANDROID_ANDROID_NATIVES_H -#define ANDROID_ANDROID_NATIVES_H - -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ - -#define ANDROID_NATIVE_MAKE_CONSTANT(a,b,c,d) \ - (((unsigned)(a)<<24)|((unsigned)(b)<<16)|((unsigned)(c)<<8)|(unsigned)(d)) - -#define ANDROID_NATIVE_WINDOW_MAGIC \ - ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d') - -#define ANDROID_NATIVE_BUFFER_MAGIC \ - ANDROID_NATIVE_MAKE_CONSTANT('_','b','f','r') - -// --------------------------------------------------------------------------- - -struct android_native_buffer_t; - -enum { - /* attributes of this surface or its updater */ - SURFACE_FLAG_PRESERVE_CONTENT = FRAMEBUFFER_RESERVED0, - SURFACE_FLAG_MAPPED = FRAMEBUFFER_FLAG_MAPPED, -}; - - -// --------------------------------------------------------------------------- - -struct android_native_base_t -{ - /* a magic value defined by the actual EGL native type */ - int magic; - - /* the sizeof() of the actual EGL native type */ - int version; - - void* reserved[4]; - - /* reference-counting interface */ - void (*incRef)(struct android_native_base_t* base); - void (*decRef)(struct android_native_base_t* base); -}; - - -struct android_native_window_t -{ -#ifdef __cplusplus - android_native_window_t() - : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0) - { - common.magic = ANDROID_NATIVE_WINDOW_MAGIC; - common.version = sizeof(android_native_window_t); - memset(common.reserved, 0, sizeof(common.reserved)); - } -#endif - - struct android_native_base_t common; - - /* flags describing some attributes of this surface or its updater */ - const uint32_t flags; - - /* min swap interval supported by this updated */ - const int minSwapInterval; - - /* max swap interval supported by this updated */ - const int maxSwapInterval; - - /* horizontal and vertical resolution in DPI */ - const float xdpi; - const float ydpi; - - /* Some storage reserved for the OEM's driver. */ - intptr_t oem[4]; - - - /* - * Set the swap interval for this surface. - * - * Returns 0 on success or -errno on error. - */ - int (*setSwapInterval)(struct android_native_window_t* window, - int interval); - - /* - * hook called by EGL to acquire a buffer. After this call, the buffer - * is not locked, so its content cannot be modified. - * this call may block if no buffers are available. - * - * Returns 0 on success or -errno on error. - */ - int (*dequeueBuffer)(struct android_native_window_t* window, - struct android_native_buffer_t** buffer); - - /* - * hook called by EGL to lock a buffer. This MUST be called before modifying - * the content of a buffer. The buffer must have been acquired with - * dequeueBuffer first. - * - * Returns 0 on success or -errno on error. - */ - int (*lockBuffer)(struct android_native_window_t* window, - struct android_native_buffer_t* buffer); - /* - * hook called by EGL when modifications to the render buffer are done. - * This unlocks and post the buffer. - * - * Buffers MUST be queued in the same order than they were dequeued. - * - * Returns 0 on success or -errno on error. - */ - int (*queueBuffer)(struct android_native_window_t* window, - struct android_native_buffer_t* buffer); - - - void* reserved_proc[5]; -}; - - -struct android_native_buffer_t -{ -#ifdef __cplusplus - android_native_buffer_t() { - common.magic = ANDROID_NATIVE_BUFFER_MAGIC; - common.version = sizeof(android_native_buffer_t); - memset(common.reserved, 0, sizeof(common.reserved)); - } -#endif - - struct android_native_base_t common; - - int width; - int height; - int stride; - int format; - int usage; - - void* reserved[2]; - - buffer_handle_t handle; - - void* reserved_proc[8]; -}; - - -/* FIXME: this is legacy for pixmaps */ -struct egl_native_pixmap_t -{ - int32_t version; /* must be 32 */ - int32_t width; - int32_t height; - int32_t stride; - uint8_t* data; - uint8_t format; - uint8_t rfu[3]; - union { - uint32_t compressedFormat; - int32_t vstride; - }; - int32_t reserved; -}; - -/*****************************************************************************/ - -#ifdef __cplusplus -} -#endif - - -/*****************************************************************************/ - -#ifdef __cplusplus - -#include - -namespace android { - -/* - * This helper class turns an EGL android_native_xxx type into a C++ - * reference-counted object; with proper type conversions. - */ -template -class EGLNativeBase : public NATIVE_TYPE, public REF -{ -protected: - typedef EGLNativeBase BASE; - EGLNativeBase() : NATIVE_TYPE(), REF() { - NATIVE_TYPE::common.incRef = incRef; - NATIVE_TYPE::common.decRef = decRef; - } - static inline TYPE* getSelf(NATIVE_TYPE* self) { - return static_cast(self); - } - static inline TYPE const* getSelf(NATIVE_TYPE const* self) { - return static_cast(self); - } - static inline TYPE* getSelf(android_native_base_t* base) { - return getSelf(reinterpret_cast(base)); - } - static inline TYPE const * getSelf(android_native_base_t const* base) { - return getSelf(reinterpret_cast(base)); - } - static void incRef(android_native_base_t* base) { - EGLNativeBase* self = getSelf(base); - self->incStrong(self); - } - static void decRef(android_native_base_t* base) { - EGLNativeBase* self = getSelf(base); - self->decStrong(self); - } -}; - -} // namespace android -#endif // __cplusplus - -/*****************************************************************************/ - -#endif /* ANDROID_ANDROID_NATIVES_H */ diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h index d42808704dd6..956149091d81 100644 --- a/opengl/include/EGL/eglplatform.h +++ b/opengl/include/EGL/eglplatform.h @@ -89,7 +89,8 @@ typedef Window EGLNativeWindowType; #elif defined(ANDROID) -#include +struct android_native_window_t; +struct egl_native_pixmap_t; typedef struct android_native_window_t* EGLNativeWindowType; typedef struct egl_native_pixmap_t* EGLNativePixmapType; @@ -97,6 +98,7 @@ typedef void* EGLNativeDisplayType; #ifndef EGL_ANDROID_image_native_buffer #define EGL_ANDROID_image_native_buffer 1 +struct android_native_buffer_t; #define EGL_NATIVE_BUFFER_ANDROID 0x6000 /* eglCreateImageKHR target */ #endif diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp index 9eb99f0bc231..e5d4ed2b6f97 100644 --- a/opengl/libagl/TextureObjectManager.cpp +++ b/opengl/libagl/TextureObjectManager.cpp @@ -19,6 +19,8 @@ #include "context.h" #include "TextureObjectManager.h" +#include + namespace android { // ---------------------------------------------------------------------------- diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h index 29d50370eb41..e0eadf147959 100644 --- a/opengl/libagl/TextureObjectManager.h +++ b/opengl/libagl/TextureObjectManager.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include "Tokenizer.h" #include "TokenManager.h" diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 720ba0bdaff3..0950f3ea2666 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -33,13 +33,14 @@ #include #include -#include #include #include #include #include +#include + #include "context.h" #include "state.h" #include "texture.h" diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index 118964340f48..0211208e2f4a 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -23,7 +23,7 @@ #include "texture.h" #include "TextureObjectManager.h" -#include +#include #ifdef LIBAGL_USE_GRALLOC_COPYBITS #include "copybit.h" -- cgit v1.2.3-59-g8ed1b From b51e18d59b6f8e44a5d3516fc3359c54fa913331 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 5 May 2009 18:21:32 -0700 Subject: move android_native_buffer_t declaration into its own private/ui/android_native_priv.h header, since user code should never have access to it. --- include/private/ui/SurfaceBuffer.h | 2 +- include/private/ui/android_natives_priv.h | 62 +++++++++++++++++++++++++++++++ include/ui/egl/android_natives.h | 26 ------------- libs/ui/FramebufferNativeWindow.cpp | 2 + opengl/libagl/TextureObjectManager.cpp | 2 +- opengl/libagl/egl.cpp | 2 +- opengl/libagl/texture.cpp | 2 +- 7 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 include/private/ui/android_natives_priv.h (limited to 'opengl/libagl/egl.cpp') diff --git a/include/private/ui/SurfaceBuffer.h b/include/private/ui/SurfaceBuffer.h index a6db50f4cf69..c45abeb73c25 100644 --- a/include/private/ui/SurfaceBuffer.h +++ b/include/private/ui/SurfaceBuffer.h @@ -22,7 +22,7 @@ #include -#include +#include namespace android { diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h new file mode 100644 index 000000000000..ee843e928100 --- /dev/null +++ b/include/private/ui/android_natives_priv.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 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. + */ + +#ifndef ANDROID_ANDROID_NATIVES_PRIV_H +#define ANDROID_ANDROID_NATIVES_PRIV_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +struct android_native_buffer_t +{ +#ifdef __cplusplus + android_native_buffer_t() { + common.magic = ANDROID_NATIVE_BUFFER_MAGIC; + common.version = sizeof(android_native_buffer_t); + memset(common.reserved, 0, sizeof(common.reserved)); + } +#endif + + struct android_native_base_t common; + + int width; + int height; + int stride; + int format; + int usage; + + void* reserved[2]; + + buffer_handle_t handle; + + void* reserved_proc[8]; +}; + + +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + +/*****************************************************************************/ + +#endif /* ANDROID_ANDROID_NATIVES_PRIV_H */ diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index 5842ee72ce7f..fa3b7a0dc78d 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -139,32 +139,6 @@ struct android_native_window_t }; -struct android_native_buffer_t -{ -#ifdef __cplusplus - android_native_buffer_t() { - common.magic = ANDROID_NATIVE_BUFFER_MAGIC; - common.version = sizeof(android_native_buffer_t); - memset(common.reserved, 0, sizeof(common.reserved)); - } -#endif - - struct android_native_base_t common; - - int width; - int height; - int stride; - int format; - int usage; - - void* reserved[2]; - - buffer_handle_t handle; - - void* reserved_proc[8]; -}; - - /* FIXME: this is legacy for pixmaps */ struct egl_native_pixmap_t { diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 5e69cff985c7..4e692e2c27a1 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -38,6 +38,8 @@ #include #include +#include + // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- diff --git a/opengl/libagl/TextureObjectManager.cpp b/opengl/libagl/TextureObjectManager.cpp index e5d4ed2b6f97..9deb2cf9eea4 100644 --- a/opengl/libagl/TextureObjectManager.cpp +++ b/opengl/libagl/TextureObjectManager.cpp @@ -19,7 +19,7 @@ #include "context.h" #include "TextureObjectManager.h" -#include +#include namespace android { // ---------------------------------------------------------------------------- diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 0950f3ea2666..1a774f59db22 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -39,7 +39,7 @@ #include #include -#include +#include #include "context.h" #include "state.h" diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index 0211208e2f4a..d675107ca0b1 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -23,7 +23,7 @@ #include "texture.h" #include "TextureObjectManager.h" -#include +#include #ifdef LIBAGL_USE_GRALLOC_COPYBITS #include "copybit.h" -- cgit v1.2.3-59-g8ed1b From 2e20bffbab8084fedce39d14d7dd17b08f6e9ba2 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Mon, 4 May 2009 19:29:25 -0700 Subject: created an new EGL extension called ANDROID_swap_rectangle ANDROID_swap_rectangle allows to specify the rectangle affected by eglSwapBuffers(), anything outside of this rectangle is unchanged. in particular EGL_BUFFER_DESTROYED only applies to that rectangle. This extension as well as EGL_BUFFER_PRESERVED allow major optimizations on surfaceflinger, which can redraw only the dirty area during compositing. However, ANDROID_swap_rectangle allows further optimizations in EGL by reducing the amount of copy-back needed. ANDROID_swap_rectangle is particularily important for software implementations. --- .../DisplayHardware/DisplayHardware.cpp | 13 +- .../DisplayHardware/DisplayHardware.h | 1 + libs/surfaceflinger/SurfaceFlinger.cpp | 14 +- opengl/include/EGL/eglext.h | 12 + opengl/libagl/egl.cpp | 269 +++++++++++++++++++-- opengl/libs/EGL/egl.cpp | 21 ++ opengl/libs/egl_entries.in | 4 + 7 files changed, 298 insertions(+), 36 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 374f2e2c8b65..fc29d73b250a 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -195,17 +195,19 @@ void DisplayHardware::init(uint32_t dpy) * Create our main surface */ - surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); checkEGLErrors("eglCreateDisplaySurfaceANDROID"); - if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { if (dummy == EGL_BUFFER_PRESERVED) { mFlags |= BUFFER_PRESERVED; } } - + + if (strstr(egl_extensions, "ANDROID_swap_rectangle")) { + mFlags |= SWAP_RECTANGLE; + } + mDpiX = mNativeWindow->xdpi; mDpiX = mNativeWindow->ydpi; mRefreshRate = mNativeWindow->getDevice()->fps; @@ -304,11 +306,12 @@ void DisplayHardware::flip(const Region& dirty) const EGLDisplay dpy = mDisplay; EGLSurface surface = mSurface; - if (mFlags & BUFFER_PRESERVED) { + if (mFlags & SWAP_RECTANGLE) { Region newDirty(dirty); newDirty.andSelf(Rect(mWidth, mHeight)); const Rect& b(newDirty.bounds()); - //mNativeWindow->setSwapRectangle(b); + eglSetSwapRectangleANDROID(dpy, surface, + b.left, b.top, b.width(), b.height()); } mPageFlipCount++; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index c9c75e27744b..c3dbff178f29 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -50,6 +50,7 @@ public: BUFFER_PRESERVED = 0x00010000, UPDATE_ON_DEMAND = 0x00020000, // video driver feature SLOW_CONFIG = 0x00040000, // software + SWAP_RECTANGLE = 0x00080000, }; DisplayHardware( diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 5fd979e0614b..b8c246cb92e7 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -803,12 +803,14 @@ void SurfaceFlinger::handleRepaint() mInvalidRegion.orSelf(mDirtyRegion); uint32_t flags = hw.getFlags(); - if (flags & DisplayHardware::BUFFER_PRESERVED) { - // here we assume DisplayHardware::flip()'s implementation - // performs the copy-back optimization. + if ((flags & DisplayHardware::SWAP_RECTANGLE) || + (flags & DisplayHardware::BUFFER_PRESERVED)) + { + // we can redraw only what's dirty } else { if (flags & DisplayHardware::UPDATE_ON_DEMAND) { - // we need to fully redraw the part that will be updated + // we need to redraw the rectangle that will be updated + // (pushed to the framebuffer). mDirtyRegion.set(mInvalidRegion.bounds()); } else { // we need to redraw everything @@ -890,7 +892,9 @@ void SurfaceFlinger::debugFlashRegions() { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t flags = hw.getFlags(); - if (!(flags & DisplayHardware::BUFFER_PRESERVED)) { + + if (!((flags & DisplayHardware::SWAP_RECTANGLE) || + (flags & DisplayHardware::BUFFER_PRESERVED))) { const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ? mDirtyRegion.bounds() : hw.bounds()); composeSurfaces(repaint); diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 25cfcb832fb2..335b0b03dabb 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -131,6 +131,18 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL /* Interfaces defined by EGL_KHR_image above */ #endif + +#ifndef EGL_ANDROID_swap_rectangle +#define EGL_ANDROID_swap_rectangle 1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSetSwapRectangleANDROID (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay dpy, EGLSurface draw, EGLint left, EGLint top, EGLint width, EGLint height); +#endif + + + + #ifdef __cplusplus } #endif diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 1a774f59db22..4cf0bf85def6 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -157,6 +157,7 @@ struct egl_surface_t virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; virtual EGLBoolean swapBuffers(); + virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); protected: GGLSurface depth; }; @@ -190,6 +191,11 @@ EGLint egl_surface_t::getRefreshRate() const { EGLint egl_surface_t::getSwapBehavior() const { return EGL_BUFFER_PRESERVED; } +EGLBoolean egl_surface_t::setSwapRectangle( + EGLint l, EGLint t, EGLint w, EGLint h) +{ + return EGL_FALSE; +} // ---------------------------------------------------------------------------- @@ -214,16 +220,104 @@ struct egl_window_surface_v2_t : public egl_surface_t virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; + virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); private: status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); status_t unlock(android_native_buffer_t* buf); android_native_window_t* nativeWindow; android_native_buffer_t* buffer; + android_native_buffer_t* previousBuffer; gralloc_module_t const* module; int width; int height; void* bits; + GGLFormat const* pixelFormatTable; + + struct Rect { + inline Rect() { }; + inline Rect(int32_t w, int32_t h) + : left(0), top(0), right(w), bottom(h) { } + inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) + : left(l), top(t), right(r), bottom(b) { } + Rect& andSelf(const Rect& r) { + left = max(left, r.left); + top = max(top, r.top); + right = min(right, r.right); + bottom = min(bottom, r.bottom); + return *this; + } + bool isEmpty() const { + return (left>=right || top>=bottom); + } + void dump(char const* what) { + LOGD("%s { %5d, %5d, w=%5d, h=%5d }", + what, left, top, right-left, bottom-top); + } + + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; + }; + + struct Region { + inline Region() : count(0) { } + static Region subtract(const Rect& lhs, const Rect& rhs) { + Region reg; + Rect* storage = reg.storage; + if (!lhs.isEmpty()) { + if (lhs.top < rhs.top) { // top rect + storage->left = lhs.left; + storage->top = lhs.top; + storage->right = lhs.right; + storage->bottom = max(lhs.top, rhs.top); + storage++; + } + if (lhs.left < rhs.left) { // left-side rect + storage->left = lhs.left; + storage->top = max(lhs.top, rhs.top); + storage->right = max(lhs.left, rhs.left); + storage->bottom = min(lhs.bottom, rhs.bottom); + storage++; + } + if (lhs.right > rhs.right) { // right-side rect + storage->left = min(lhs.right, rhs.right); + storage->top = max(lhs.top, rhs.top); + storage->right = lhs.right; + storage->bottom = min(lhs.bottom, rhs.bottom); + storage++; + } + if (lhs.bottom > rhs.bottom) { // bottom rect + storage->left = lhs.left; + storage->top = min(lhs.bottom, rhs.bottom); + storage->right = lhs.right; + storage->bottom = lhs.bottom; + storage++; + } + reg.count = storage - reg.storage; + } + return reg; + } + bool isEmpty() const { + return count<=0; + } + ssize_t getRects(Rect const* * rects) const { + *rects = storage; + return count; + } + private: + Rect storage[4]; + ssize_t count; + }; + + void copyBlt( + android_native_buffer_t* dst, void* dst_vaddr, + android_native_buffer_t* src, void const* src_vaddr, + const Rect* reg, ssize_t count); + + Rect dirtyRegion; + Rect oldDirtyRegion; }; egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, @@ -231,16 +325,22 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, int32_t depthFormat, android_native_window_t* window) : egl_surface_t(dpy, config, depthFormat), - nativeWindow(window), buffer(0), module(0), bits(NULL) + nativeWindow(window), buffer(0), previousBuffer(0), module(0), + bits(NULL) { hw_module_t const* pModule; hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); module = reinterpret_cast(pModule); + pixelFormatTable = gglGetPixelFormatTable(); + + // keep a reference on the window nativeWindow->common.incRef(&nativeWindow->common); + // dequeue a buffer nativeWindow->dequeueBuffer(nativeWindow, &buffer); - + + // allocate a corresponding depth-buffer width = buffer->width; height = buffer->height; if (depthFormat) { @@ -254,14 +354,32 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, } } + // keep a reference on the buffer buffer->common.incRef(&buffer->common); } +egl_window_surface_v2_t::~egl_window_surface_v2_t() { + if (buffer) { + buffer->common.decRef(&buffer->common); + } + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + } + nativeWindow->common.decRef(&nativeWindow->common); +} + void egl_window_surface_v2_t::connect() { // Lock the buffer nativeWindow->lockBuffer(nativeWindow, buffer); - lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits); + // pin the buffer down + if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { + LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", + buffer, buffer->width, buffer->height); + setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); + // FIXME: we should make sure we're not accessing the buffer anymore + } } void egl_window_surface_v2_t::disconnect() @@ -286,38 +404,86 @@ status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) return err; } +void egl_window_surface_v2_t::copyBlt( + android_native_buffer_t* dst, void* dst_vaddr, + android_native_buffer_t* src, void const* src_vaddr, + const Rect* reg, ssize_t count) +{ + // FIXME: use copybit if possible + // NOTE: dst and src must be the same format + + Rect r; + const size_t bpp = pixelFormatTable[src->format].size; + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; -egl_window_surface_v2_t::~egl_window_surface_v2_t() { - if (buffer) { - buffer->common.decRef(&buffer->common); + uint8_t const * const src_bits = (uint8_t const *)src_vaddr; + uint8_t * const dst_bits = (uint8_t *)dst_vaddr; + + for (int i= 0 ; istride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; + } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); } - nativeWindow->common.decRef(&nativeWindow->common); } EGLBoolean egl_window_surface_v2_t::swapBuffers() { - // TODO: this is roughly the code needed for preserving the back buffer - // efficiently. dirty is the area that has been modified. - //Region newDirty(dirty); - //newDirty.andSelf(Rect(nativeWindow->width, nativeWindow->height)); - //mDirty = newDirty; - //const Region copyback(mDirty.subtract(newDirty)); - //mDisplaySurface->copyFrontToBack(copyback); + /* + * Handle eglSetSwapRectangleANDROID() + * We copyback from the front buffer + */ + if (!dirtyRegion.isEmpty()) { + dirtyRegion.andSelf(Rect(buffer->width, buffer->height)); + if (previousBuffer) { + const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); + if (!copyBack.isEmpty()) { + Rect const* list; + ssize_t count = copyBack.getRects(&list); + // copy from previousBuffer to buffer + void* prevBits; + if (lock(previousBuffer, + GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) + { + copyBlt(buffer, bits, previousBuffer, prevBits, list, count); + unlock(previousBuffer); + } + } + } + oldDirtyRegion = dirtyRegion; + } + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + previousBuffer = 0; + } unlock(buffer); + previousBuffer = buffer; nativeWindow->queueBuffer(nativeWindow, buffer); - buffer->common.decRef(&buffer->common); buffer = 0; + buffer = 0; + // dequeue a new buffer nativeWindow->dequeueBuffer(nativeWindow, &buffer); - buffer->common.incRef(&buffer->common); - + // TODO: lockBuffer should rather be executed when the very first // direct rendering occurs. - void* vaddr; nativeWindow->lockBuffer(nativeWindow, buffer); - lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits); + // reallocate the depth-buffer if needed if ((width != buffer->width) || (height != buffer->height)) { // TODO: we probably should reset the swap rect here // if the window size has changed @@ -330,11 +496,31 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers() depth.stride = buffer->stride; depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); if (depth.data == 0) { - setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + setError(EGL_BAD_ALLOC, EGL_FALSE); return EGL_FALSE; } } } + + // keep a reference on the buffer + buffer->common.incRef(&buffer->common); + + // finally pin the buffer down + if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { + LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", + buffer, buffer->width, buffer->height); + setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); + // FIXME: we should make sure we're not accessing the buffer anymore + } + + return EGL_TRUE; +} + +EGLBoolean egl_window_surface_v2_t::setSwapRectangle( + EGLint l, EGLint t, EGLint w, EGLint h) +{ + dirtyRegion = Rect(l, t, l+w, t+h); return EGL_TRUE; } @@ -402,12 +588,22 @@ EGLint egl_window_surface_v2_t::getVerticalResolution() const { EGLint egl_window_surface_v2_t::getRefreshRate() const { return (60 * EGL_DISPLAY_SCALING); // FIXME } -EGLint egl_window_surface_v2_t::getSwapBehavior() const { - //uint32_t flags = nativeWindow->flags; - //if (flags & SURFACE_FLAG_PRESERVE_CONTENT) - // return EGL_BUFFER_PRESERVED; - // This is now a feature of EGL, currently we don't preserve - // the content of the buffers. +EGLint egl_window_surface_v2_t::getSwapBehavior() const +{ + /* + * EGL_BUFFER_PRESERVED means that eglSwapBuffers() completely preserves + * the content of the swapped buffer. + * + * EGL_BUFFER_DESTROYED means that the content of the buffer is lost. + * + * However when ANDROID_swap_retcangle is supported, EGL_BUFFER_DESTROYED + * only applies to the area specified by eglSetSwapRectangleANDROID(), that + * is, everything outside of this area is preserved. + * + * This implementation of EGL assumes the later case. + * + */ + return EGL_BUFFER_DESTROYED; } @@ -581,6 +777,7 @@ static char const * const gExtensionsString = "KHR_image_base " // "KHR_image_pixmap " "EGL_ANDROID_image_native_buffer " + "EGL_ANDROID_swap_rectangle " ; // ---------------------------------------------------------------------------- @@ -1765,3 +1962,23 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) return EGL_TRUE; } + +// ---------------------------------------------------------------------------- +// ANDROID extensions +// ---------------------------------------------------------------------------- + +EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, + EGLint left, EGLint top, EGLint width, EGLint height) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + egl_surface_t* d = static_cast(draw); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, EGL_FALSE); + + // post the surface + d->setSwapRectangle(left, top, width, height); + + return EGL_TRUE; +} diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 74aed2062055..8c37f2e8b695 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -60,6 +60,7 @@ static char const * const gExtensionString = "KHR_image_base " "KHR_image_pixmap " "EGL_ANDROID_image_native_buffer " + "EGL_ANDROID_swap_rectangle " ; // ---------------------------------------------------------------------------- @@ -1568,3 +1569,23 @@ EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) return EGL_FALSE; } + + +// ---------------------------------------------------------------------------- +// ANDROID extensions +// ---------------------------------------------------------------------------- + +EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, + EGLint left, EGLint top, EGLint width, EGLint height) +{ + if (!validate_display_surface(dpy, draw)) + return EGL_FALSE; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(draw); + if (s->cnx->hooks->egl.eglSetSwapRectangleANDROID) { + return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl], + s->surface, left, top, width, height); + } + return EGL_FALSE; +} + diff --git a/opengl/libs/egl_entries.in b/opengl/libs/egl_entries.in index 3b4551b63964..1fe2b5702d34 100644 --- a/opengl/libs/egl_entries.in +++ b/opengl/libs/egl_entries.in @@ -50,3 +50,7 @@ EGL_ENTRY(EGLBoolean, eglLockSurfaceKHR, EGLDisplay, EGLSurface, const EGLint EGL_ENTRY(EGLBoolean, eglUnlockSurfaceKHR, EGLDisplay, EGLSurface) EGL_ENTRY(EGLImageKHR, eglCreateImageKHR, EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *) EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR) + +/* ANDROID extensions */ + +EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) -- cgit v1.2.3-59-g8ed1b From 927d37cb788670b91af0f1a7a93c68046a838d23 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 6 May 2009 23:47:08 -0700 Subject: fix EGL extension string names --- libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp | 4 ++-- opengl/libagl/egl.cpp | 2 +- opengl/libs/EGL/egl.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index fc29d73b250a..31db31f9abb5 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -204,7 +204,7 @@ void DisplayHardware::init(uint32_t dpy) } } - if (strstr(egl_extensions, "ANDROID_swap_rectangle")) { + if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) { mFlags |= SWAP_RECTANGLE; } @@ -250,7 +250,7 @@ void DisplayHardware::init(uint32_t dpy) mFlags |= DRAW_TEXTURE_EXTENSION; } if (strstr( gl_extensions, "GL_OES_EGL_image") && - (strstr(egl_extensions, "KHR_image_base") || + (strstr(egl_extensions, "EGL_KHR_image_base") || strstr(egl_extensions, "EGL_KHR_image")) && strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) { mFlags |= DIRECT_TEXTURE; diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 4cf0bf85def6..f50257abb7e8 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -774,7 +774,7 @@ static char const * const gVendorString = "Google Inc."; static char const * const gVersionString = "1.2 Android Driver"; static char const * const gClientApiString = "OpenGL ES"; static char const * const gExtensionsString = - "KHR_image_base " + "EGL_KHR_image_base " // "KHR_image_pixmap " "EGL_ANDROID_image_native_buffer " "EGL_ANDROID_swap_rectangle " diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 8c37f2e8b695..6c805388ce8a 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -57,8 +57,8 @@ static char const * const gVersionString = "1.31 Android META-EGL"; static char const * const gClientApiString = "OpenGL ES"; static char const * const gExtensionString = "EGL_KHR_image " - "KHR_image_base " - "KHR_image_pixmap " + "EGL_KHR_image_base " + "EGL_KHR_image_pixmap " "EGL_ANDROID_image_native_buffer " "EGL_ANDROID_swap_rectangle " ; -- cgit v1.2.3-59-g8ed1b From 36432ccc13f6d3db7af35661683c33ffa3406d85 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 3 Jun 2009 19:00:53 -0700 Subject: make sure clear the draw and read EGLSurface when eglMakeCurrent() is called for unbinding from the thread --- opengl/libagl/egl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index f50257abb7e8..0df2bbaa584f 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -384,7 +384,7 @@ void egl_window_surface_v2_t::connect() void egl_window_surface_v2_t::disconnect() { - if (buffer) { + if (buffer && bits) { bits = NULL; unlock(buffer); } @@ -1681,10 +1681,12 @@ EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, egl_surface_t* d = (egl_surface_t*)c->draw; egl_surface_t* r = (egl_surface_t*)c->read; if (d) { + c->draw = 0; d->ctx = EGL_NO_CONTEXT; d->disconnect(); } if (r) { + c->read = 0; r->ctx = EGL_NO_CONTEXT; // FIXME: unlock/disconnect the read surface too } -- 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/egl.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 c1e3ec555b79b1e45fccbdf0bbc8ac2d51902860 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 24 Jun 2009 22:37:39 -0700 Subject: Add eglGetRenderBufferANDROID() extension, which returns the current render buffer as an android_native_buffer_t* --- opengl/include/EGL/eglext.h | 16 +++++++++++-- opengl/include/EGL/eglplatform.h | 6 ----- opengl/libagl/TextureObjectManager.h | 1 + opengl/libagl/egl.cpp | 45 +++++++++++++++++++++++++++++++----- opengl/libs/EGL/egl.cpp | 17 ++++++++++++++ opengl/libs/EGL/egl_entries.in | 1 + 6 files changed, 72 insertions(+), 14 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h index 335b0b03dabb..545fd0e980bd 100644 --- a/opengl/include/EGL/eglext.h +++ b/opengl/include/EGL/eglext.h @@ -132,6 +132,20 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGL #endif +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +struct android_native_buffer_t; +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 /* eglCreateImageKHR target */ +#endif + +#ifndef EGL_ANDROID_get_render_buffer +#define EGL_ANDROID_get_render_buffer 1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLClientBuffer EGLAPIENTRY eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw); +#endif +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETRENDERBUFFERANDROIDPROC) (EGLDisplay dpy, EGLSurface draw); +#endif + #ifndef EGL_ANDROID_swap_rectangle #define EGL_ANDROID_swap_rectangle 1 #ifdef EGL_EGLEXT_PROTOTYPES @@ -141,8 +155,6 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSWAPRECTANGLEANDROIDPROC) (EGLDisplay #endif - - #ifdef __cplusplus } #endif diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h index 11aa4e2f4135..53e9e61169b1 100644 --- a/opengl/include/EGL/eglplatform.h +++ b/opengl/include/EGL/eglplatform.h @@ -96,12 +96,6 @@ typedef struct android_native_window_t* EGLNativeWindowType; typedef struct egl_native_pixmap_t* EGLNativePixmapType; typedef void* EGLNativeDisplayType; -#ifndef EGL_ANDROID_image_native_buffer -#define EGL_ANDROID_image_native_buffer 1 -struct android_native_buffer_t; -#define EGL_NATIVE_BUFFER_ANDROID 0x3140 /* eglCreateImageKHR target */ -#endif - #else #error "Platform not recognized" #endif diff --git a/opengl/libagl/TextureObjectManager.h b/opengl/libagl/TextureObjectManager.h index 496e6947d737..279e0406c212 100644 --- a/opengl/libagl/TextureObjectManager.h +++ b/opengl/libagl/TextureObjectManager.h @@ -31,6 +31,7 @@ #include #include +#include #include "Tokenizer.h" #include "TokenManager.h" diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index c6d50578869a..f6ffc53cfba8 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -158,6 +158,7 @@ struct egl_surface_t virtual EGLint getSwapBehavior() const; virtual EGLBoolean swapBuffers(); virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); + virtual EGLClientBuffer getRenderBuffer() const; protected: GGLSurface depth; }; @@ -196,6 +197,9 @@ EGLBoolean egl_surface_t::setSwapRectangle( { return EGL_FALSE; } +EGLClientBuffer egl_surface_t::getRenderBuffer() const { + return 0; +} // ---------------------------------------------------------------------------- @@ -221,7 +225,8 @@ struct egl_window_surface_v2_t : public egl_surface_t virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; virtual EGLBoolean setSwapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); - + virtual EGLClientBuffer getRenderBuffer() const; + private: status_t lock(android_native_buffer_t* buf, int usage, void** vaddr); status_t unlock(android_native_buffer_t* buf); @@ -524,18 +529,24 @@ EGLBoolean egl_window_surface_v2_t::setSwapRectangle( return EGL_TRUE; } +EGLClientBuffer egl_window_surface_v2_t::getRenderBuffer() const +{ + return buffer; +} + #ifdef LIBAGL_USE_GRALLOC_COPYBITS static bool supportedCopybitsDestinationFormat(int format) { - // Hardware supported and no destination alpha + // Hardware supported switch (format) { case HAL_PIXEL_FORMAT_RGB_565: - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBA_4444: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_BGRA_8888: return true; - default: - return false; } + return false; } #endif @@ -778,6 +789,7 @@ static char const * const gExtensionsString = // "KHR_image_pixmap " "EGL_ANDROID_image_native_buffer " "EGL_ANDROID_swap_rectangle " + "EGL_ANDROID_get_render_buffer " ; // ---------------------------------------------------------------------------- @@ -824,6 +836,14 @@ static const extention_map_t gExtentionMap[] = { (__eglMustCastToProperFunctionPointerType)&glDeleteBuffers }, { "glGenBuffers", (__eglMustCastToProperFunctionPointerType)&glGenBuffers }, + { "eglCreateImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, + { "eglDestroyImageKHR", + (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, + { "eglSetSwapRectangleANDROID", + (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, + { "eglGetRenderBufferANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID }, }; /* @@ -1984,3 +2004,16 @@ EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, return EGL_TRUE; } + +EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw) +{ + if (egl_display_t::is_valid(dpy) == EGL_FALSE) + return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0); + + egl_surface_t* d = static_cast(draw); + if (d->dpy != dpy) + return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0); + + // post the surface + return d->getRenderBuffer(); +} diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index fec4e5d3a3d3..004b74aedd17 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -58,6 +58,7 @@ static char const * const gExtensionString = "EGL_KHR_image_pixmap " "EGL_ANDROID_image_native_buffer " "EGL_ANDROID_swap_rectangle " + "EGL_ANDROID_get_render_buffer " ; // ---------------------------------------------------------------------------- @@ -303,6 +304,10 @@ static const extention_map_t gExtentionMap[] = { (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, { "eglDestroyImageKHR", (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, + { "eglSetSwapRectangleANDROID", + (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, + { "eglGetRenderBufferANDROID", + (__eglMustCastToProperFunctionPointerType)&eglGetRenderBufferANDROID }, }; static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS]; @@ -1484,3 +1489,15 @@ EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, return EGL_FALSE; } +EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw) +{ + if (!validate_display_surface(dpy, draw)) + return 0; + egl_display_t const * const dp = get_display(dpy); + egl_surface_t const * const s = get_surface(draw); + if (s->cnx->hooks->egl.eglGetRenderBufferANDROID) { + return s->cnx->hooks->egl.eglGetRenderBufferANDROID(dp->dpys[s->impl], + s->surface); + } + return 0; +} diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in index 1fe2b5702d34..5d892872806a 100644 --- a/opengl/libs/EGL/egl_entries.in +++ b/opengl/libs/EGL/egl_entries.in @@ -54,3 +54,4 @@ EGL_ENTRY(EGLBoolean, eglDestroyImageKHR, EGLDisplay, EGLImageKHR) /* ANDROID extensions */ EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint) +EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface) -- cgit v1.2.3-59-g8ed1b From 68eeb80a54f411b9a8c928cc193de731adddb6c3 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 25 Jun 2009 15:39:25 -0700 Subject: use copybit for eglSwapBuffers() copy-back operations --- libs/surfaceflinger/LayerBuffer.cpp | 5 +- opengl/libagl/egl.cpp | 161 ++++++++++++++++++++++++------------ 2 files changed, 113 insertions(+), 53 deletions(-) (limited to 'opengl/libagl/egl.cpp') diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index d70a71f4568c..1827efad8a78 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -341,6 +341,9 @@ LayerBuffer::BufferSource::~BufferSource() if (mTexture.name != -1U) { glDeleteTextures(1, &mTexture.name); } + if (mBlitEngine) { + copybit_close(mBlitEngine); + } } void LayerBuffer::BufferSource::postBuffer(ssize_t offset) @@ -485,7 +488,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const const Rect& transformedBounds = mLayer.getTransformedBounds(); const copybit_rect_t& drect - = reinterpret_cast(transformedBounds); + = reinterpret_cast(transformedBounds); const State& s(mLayer.drawingState()); region_iterator it(clip); diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index f6ffc53cfba8..0fc934f0d5fa 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -41,6 +41,8 @@ #include +#include + #include "context.h" #include "state.h" #include "texture.h" @@ -234,6 +236,7 @@ private: android_native_buffer_t* buffer; android_native_buffer_t* previousBuffer; gralloc_module_t const* module; + copybit_device_t* blitengine; int width; int height; void* bits; @@ -268,6 +271,9 @@ private: struct Region { inline Region() : count(0) { } + typedef Rect const* const_iterator; + const_iterator begin() const { return storage; } + const_iterator end() const { return storage+count; } static Region subtract(const Rect& lhs, const Rect& rhs) { Region reg; Rect* storage = reg.storage; @@ -276,26 +282,30 @@ private: storage->left = lhs.left; storage->top = lhs.top; storage->right = lhs.right; - storage->bottom = max(lhs.top, rhs.top); + storage->bottom = rhs.top; storage++; } - if (lhs.left < rhs.left) { // left-side rect - storage->left = lhs.left; - storage->top = max(lhs.top, rhs.top); - storage->right = max(lhs.left, rhs.left); - storage->bottom = min(lhs.bottom, rhs.bottom); - storage++; - } - if (lhs.right > rhs.right) { // right-side rect - storage->left = min(lhs.right, rhs.right); - storage->top = max(lhs.top, rhs.top); - storage->right = lhs.right; - storage->bottom = min(lhs.bottom, rhs.bottom); - storage++; + const int32_t top = max(lhs.top, rhs.top); + const int32_t bot = min(lhs.bottom, rhs.bottom); + if (top < bot) { + if (lhs.left < rhs.left) { // left-side rect + storage->left = lhs.left; + storage->top = top; + storage->right = rhs.left; + storage->bottom = bot; + storage++; + } + if (lhs.right > rhs.right) { // right-side rect + storage->left = rhs.right; + storage->top = top; + storage->right = lhs.right; + storage->bottom = bot; + storage++; + } } if (lhs.bottom > rhs.bottom) { // bottom rect storage->left = lhs.left; - storage->top = min(lhs.bottom, rhs.bottom); + storage->top = rhs.bottom; storage->right = lhs.right; storage->bottom = lhs.bottom; storage++; @@ -307,19 +317,33 @@ private: bool isEmpty() const { return count<=0; } - ssize_t getRects(Rect const* * rects) const { - *rects = storage; - return count; - } private: Rect storage[4]; ssize_t count; }; + struct region_iterator : public copybit_region_t { + region_iterator(const Region& region) + : b(region.begin()), e(region.end()) { + this->next = iterate; + } + private: + static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { + region_iterator const* me = static_cast(self); + if (me->b != me->e) { + *reinterpret_cast(rect) = *me->b++; + return 1; + } + return 0; + } + mutable Region::const_iterator b; + Region::const_iterator const e; + }; + void copyBlt( android_native_buffer_t* dst, void* dst_vaddr, android_native_buffer_t* src, void const* src_vaddr, - const Rect* reg, ssize_t count); + const Region& clip); Rect dirtyRegion; Rect oldDirtyRegion; @@ -331,12 +355,16 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, android_native_window_t* window) : egl_surface_t(dpy, config, depthFormat), nativeWindow(window), buffer(0), previousBuffer(0), module(0), - bits(NULL) + blitengine(0), bits(NULL) { hw_module_t const* pModule; hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule); module = reinterpret_cast(pModule); + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &pModule) == 0) { + copybit_open(pModule, &blitengine); + } + pixelFormatTable = gglGetPixelFormatTable(); // keep a reference on the window @@ -371,6 +399,9 @@ egl_window_surface_v2_t::~egl_window_surface_v2_t() { previousBuffer->common.decRef(&previousBuffer->common); } nativeWindow->common.decRef(&nativeWindow->common); + if (blitengine) { + copybit_close(blitengine); + } } void egl_window_surface_v2_t::connect() @@ -380,7 +411,7 @@ void egl_window_surface_v2_t::connect() // pin the buffer down if (lock(buffer, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, &bits) != NO_ERROR) { - LOGE("eglSwapBuffers() failed to lock buffer %p (%ux%u)", + LOGE("connect() failed to lock buffer %p (%ux%u)", buffer, buffer->width, buffer->height); setError(EGL_BAD_ACCESS, EGL_NO_SURFACE); // FIXME: we should make sure we're not accessing the buffer anymore @@ -412,36 +443,65 @@ status_t egl_window_surface_v2_t::unlock(android_native_buffer_t* buf) void egl_window_surface_v2_t::copyBlt( android_native_buffer_t* dst, void* dst_vaddr, android_native_buffer_t* src, void const* src_vaddr, - const Rect* reg, ssize_t count) + const Region& clip) { // FIXME: use copybit if possible // NOTE: dst and src must be the same format - Rect r; - const size_t bpp = pixelFormatTable[src->format].size; - const size_t dbpr = dst->stride * bpp; - const size_t sbpr = src->stride * bpp; + status_t err = NO_ERROR; + copybit_device_t* const copybit = blitengine; + if (copybit) { + copybit_image_t simg; + simg.w = src->width; + simg.h = src->height; + simg.format = src->format; + simg.handle = const_cast(src->handle); + + copybit_image_t dimg; + dimg.w = dst->width; + dimg.h = dst->height; + dimg.format = dst->format; + dimg.handle = const_cast(dst->handle); + + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE); + region_iterator it(clip); + err = copybit->blit(copybit, &dimg, &simg, &it); + if (err != NO_ERROR) { + LOGE("copybit failed (%s)", strerror(err)); + } + } - uint8_t const * const src_bits = (uint8_t const *)src_vaddr; - uint8_t * const dst_bits = (uint8_t *)dst_vaddr; - - for (int i= 0 ; istride * r.top) * bpp; - uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; - if (dbpr==sbpr && size==sbpr) { - size *= h; - h = 1; + if (!copybit || err) { + Region::const_iterator cur = clip.begin(); + Region::const_iterator end = clip.end(); + + const size_t bpp = pixelFormatTable[src->format].size; + const size_t dbpr = dst->stride * bpp; + const size_t sbpr = src->stride * bpp; + + uint8_t const * const src_bits = (uint8_t const *)src_vaddr; + uint8_t * const dst_bits = (uint8_t *)dst_vaddr; + + while (cur != end) { + const Rect& r(*cur++); + ssize_t w = r.right - r.left; + ssize_t h = r.bottom - r.top; + if (w <= 0 || h<=0) continue; + size_t size = w * bpp; + uint8_t const * s = src_bits + (r.left + src->stride * r.top) * bpp; + uint8_t * d = dst_bits + (r.left + dst->stride * r.top) * bpp; + if (dbpr==sbpr && size==sbpr) { + size *= h; + h = 1; + } + do { + memcpy(d, s, size); + d += dbpr; + s += sbpr; + } while (--h > 0); } - do { - memcpy(d, s, size); - d += dbpr; - s += sbpr; - } while (--h > 0); } } @@ -456,14 +516,11 @@ EGLBoolean egl_window_surface_v2_t::swapBuffers() if (previousBuffer) { const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion)); if (!copyBack.isEmpty()) { - Rect const* list; - ssize_t count = copyBack.getRects(&list); - // copy from previousBuffer to buffer void* prevBits; if (lock(previousBuffer, - GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) - { - copyBlt(buffer, bits, previousBuffer, prevBits, list, count); + GRALLOC_USAGE_SW_READ_OFTEN, &prevBits) == NO_ERROR) { + // copy from previousBuffer to buffer + copyBlt(buffer, bits, previousBuffer, prevBits, copyBack); unlock(previousBuffer); } } -- cgit v1.2.3-59-g8ed1b