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/array.cpp | 109 ++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 50 deletions(-) (limited to 'opengl/libagl/array.cpp') diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index 8fa7566aacc0..eefe614c2fb7 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -1,16 +1,16 @@ -/* +/* ** Copyright 2006, 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. */ @@ -26,6 +26,9 @@ #include "primitives.h" #include "texture.h" #include "BufferObjectManager.h" +#ifdef LIBAGL_USE_GRALLOC_COPYBITS +#include "copybit.h" +#endif // LIBAGL_USE_GRALLOC_COPYBITS // ---------------------------------------------------------------------------- @@ -250,7 +253,7 @@ static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) { v[2] = GGL_S_TO_X(p[2]); } -typedef array_t::fetcher_t fn_t; +typedef array_t::fetcher_t fn_t; static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x} { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0, @@ -334,7 +337,7 @@ void array_t::init( this->bounds = count; } -inline void array_t::resolve() +inline void array_t::resolve() { physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer; } @@ -465,7 +468,7 @@ vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index) // We compute directly the index of a "free" entry from the locked // state of v[2] and v[3]. v = c->vc.vBuffer + 2; - v += v[0].locked | (v[1].locked<<1); + v += v[0].locked | (v[1].locked<<1); } // note: compileElement clears v->flags c->arrays.compileElement(c, v, index); @@ -480,7 +483,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index) #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED - vertex_t* const v = c->vc.vCache + + vertex_t* const v = c->vc.vCache + (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1)); if (ggl_likely(v->index == index)) { @@ -491,7 +494,7 @@ vertex_t* fetch_vertex(ogles_context_t* c, size_t index) #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU - vertex_t* v = c->vc.vCache + + vertex_t* v = c->vc.vCache + (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2; // always record LRU in v[0] @@ -532,12 +535,12 @@ void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 1 - const GLsizei vcs = + const GLsizei vcs = (vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE); do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -569,13 +572,13 @@ void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count) count -= 1; // vertex cache size must be multiple of 1 - const GLsizei vcs = + const GLsizei vcs = (vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE - 1); do { - v0 = c->vc.vBuffer + 0; + v0 = c->vc.vBuffer + 0; v = c->vc.vBuffer + 1; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.compileElements(c, v, first, num); first += num; count -= num; @@ -602,7 +605,7 @@ void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count) return; drawPrimitivesLineStrip(c, first, count); if (ggl_likely(count >= 3)) { - vertex_t* v0 = c->vc.vBuffer; + vertex_t* v0 = c->vc.vBuffer; vertex_t* v1 = c->vc.vBuffer + 1; c->arrays.compileElement(c, v1, first); const uint32_t cc = v0->flags & v1->flags; @@ -617,12 +620,12 @@ void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 2 - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2; do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -662,14 +665,14 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, // because it allows us to preserve the same winding when the whole // batch is culled. We also need 2 extra vertices in the array, because // we always keep the two first ones. - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2; do { - v0 = c->vc.vBuffer + 0; - v1 = c->vc.vBuffer + 1; + v0 = c->vc.vBuffer + 0; + v1 = c->vc.vBuffer + 1; v = c->vc.vBuffer + 2; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.compileElements(c, v, first, num); first += num; count -= num; @@ -697,13 +700,19 @@ static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c, } while (count > 0); } -void drawPrimitivesTriangleStrip(ogles_context_t* c, +void drawPrimitivesTriangleStrip(ogles_context_t* c, GLint first, GLsizei count) { drawPrimitivesTriangleFanOrStrip(c, first, count, 1); } void drawPrimitivesTriangleFan(ogles_context_t* c, GLint first, GLsizei count) { +#ifdef LIBAGL_USE_GRALLOC_COPYBITS + if (drawTrangleFanWithCopybit(c, first, count)) { + return; + } +#endif // LIBAGL_USE_GRALLOC_COPYBITS + drawPrimitivesTriangleFanOrStrip(c, first, count, 2); } @@ -713,12 +722,12 @@ void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count) return; // vertex cache size must be multiple of 3 - const GLsizei vcs = + const GLsizei vcs = ((vertex_cache_t::VERTEX_BUFFER_SIZE + vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3; do { vertex_t* v = c->vc.vBuffer; - GLsizei num = count > vcs ? vcs : count; + GLsizei num = count > vcs ? vcs : count; c->arrays.cull = vertex_t::CLIP_ALL; c->arrays.compileElements(c, v, first, num); first += num; @@ -779,11 +788,11 @@ void drawIndexedPrimitivesLineStrip(ogles_context_t* c, { if (ggl_unlikely(count < 2)) return; - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1; - + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); c->arrays.compileElement(c, v0, read_index(type, indices)); count -= 1; @@ -806,11 +815,11 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c, drawIndexedPrimitivesLines(c, count, indices); return; } - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1; - + const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE); c->arrays.compileElement(c, v0, read_index(type, indices)); count -= 1; @@ -825,7 +834,7 @@ void drawIndexedPrimitivesLineLoop(ogles_context_t* c, } while (count); v1->locked = 0; - v1 = c->vc.vBuffer; + v1 = c->vc.vBuffer; const uint32_t cc = v0->flags & v1->flags; if (ggl_likely(!(cc & vertex_t::CLIP_ALL))) c->prims.renderLine(c, v0, v1); @@ -861,7 +870,7 @@ static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c, if (ggl_unlikely(count < 3)) return; - + vertex_t * const v = c->vc.vBuffer; vertex_t* v0 = v; vertex_t* v1 = v+1; @@ -981,17 +990,17 @@ void compileElements__3x_full(ogles_context_t* c, const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first); const size_t stride = c->arrays.vertex.stride / 4; // const GLfixed* const& m = c->transforms.mvp.matrix.m; - + GLfixed m[16]; memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m)); - + do { const GLfixed rx = vp[0]; const GLfixed ry = vp[1]; const GLfixed rz = vp[2]; vp += stride; v->index = first++; - v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); + v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]); v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]); v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]); v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]); @@ -1019,7 +1028,7 @@ void compileElements__3x_full(ogles_context_t* c, #pragma mark clippers #endif -static void clipVec4(vec4_t& nv, +static void clipVec4(vec4_t& nv, GLfixed t, const vec4_t& s, const vec4_t& p) { for (int i=0; i<4 ; i++) @@ -1082,10 +1091,10 @@ void validate_arrays(ogles_context_t* c, GLenum mode) // automatically turn it off (in fact we could when the 4th coordinate // is not spcified in the vertex array). // W interpolation is never needed for points. - GLboolean perspective = + GLboolean perspective = c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS); c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective); - + // set anti-aliasing GLboolean smooth = GL_FALSE; switch (mode) { @@ -1116,7 +1125,7 @@ void validate_arrays(ogles_context_t* c, GLenum mode) if (enables & GGL_ENABLE_TMUS) { // needs texture transforms want |= transform_state_t::TEXTURE; } - if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { + if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) { want |= transform_state_t::MODELVIEW; // needs eye coords } ogles_validate_transform(c, want); @@ -1135,18 +1144,18 @@ void validate_arrays(ogles_context_t* c, GLenum mode) c->arrays.mv_transform = c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2]; - + /* * *********************************************************************** * pick fetchers * *********************************************************************** */ - + array_machine_t& am = c->arrays; am.vertex.fetch = fetchNop; am.normal.fetch = currentNormal; am.color.fetch = currentColor; - + if (am.vertex.enable) { am.vertex.resolve(); if (am.vertex.bo || am.vertex.pointer) { @@ -1409,7 +1418,7 @@ void glDrawElements( // clear the vertex-cache c->vc.clear(); validate_arrays(c, mode); - + // if indices are in a buffer object, the pointer is treated as an // offset in that buffer. if (c->arrays.element_array_buffer) { @@ -1444,7 +1453,7 @@ void glBindBuffer(GLenum target, GLuint buffer) return; } } - ((target == GL_ARRAY_BUFFER) ? + ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer) = bo; } @@ -1463,7 +1472,7 @@ void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usa ogles_error(c, GL_INVALID_ENUM); return; } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer); if (bo == 0) { @@ -1493,7 +1502,7 @@ void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvo ogles_error(c, GL_INVALID_VALUE); return; } - buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? + buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ? c->arrays.array_buffer : c->arrays.element_array_buffer); if (bo == 0) { @@ -1541,7 +1550,7 @@ void glDeleteBuffers(GLsizei n, const GLuint* buffers) } } } - } + } c->bufferObjectManager->deleteBuffers(n, buffers); c->bufferObjectManager->recycleTokens(n, buffers); } -- 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/array.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 03a1b0116b115c214c16fa1a02a46999312fd0f2 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 17 Jun 2009 21:18:56 -0700 Subject: s/w OpenGL no detects and handles all any combinations of triangle fans corresponding to a rectangle this allows fallback to faster copybit code in almost all cases. --- opengl/libagl/array.cpp | 2 +- opengl/libagl/copybit.cpp | 187 ++++++++++++++++++++++++++++------------------ opengl/libagl/copybit.h | 10 +-- 3 files changed, 122 insertions(+), 77 deletions(-) (limited to 'opengl/libagl/array.cpp') diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp index cffe880edd0d..f414ee5f7c3a 100644 --- a/opengl/libagl/array.cpp +++ b/opengl/libagl/array.cpp @@ -708,7 +708,7 @@ void drawPrimitivesTriangleStrip(ogles_context_t* c, void drawPrimitivesTriangleFan(ogles_context_t* c, GLint first, GLsizei count) { #ifdef LIBAGL_USE_GRALLOC_COPYBITS - if (drawTrangleFanWithCopybit(c, first, count)) { + if (drawTriangleFanWithCopybit(c, first, count)) { return; } #endif // LIBAGL_USE_GRALLOC_COPYBITS diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp index d57a6e429081..0736b6b7b374 100644 --- a/opengl/libagl/copybit.cpp +++ b/opengl/libagl/copybit.cpp @@ -34,6 +34,9 @@ #include #include "gralloc_priv.h" + +#define DEBUG_COPYBIT true + // ---------------------------------------------------------------------------- namespace android { @@ -114,9 +117,14 @@ static bool checkContext(ogles_context_t* c) { // By convention copybitQuickCheckContext() has already returned true. // avoid checking the same information again. - if (c->copybits.blitEngine == NULL - || (c->rasterizer.state.enables - & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) != 0) { + if (c->copybits.blitEngine == NULL) { + LOGD_IF(DEBUG_COPYBIT, "no copybit hal"); + return false; + } + + if (c->rasterizer.state.enables + & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)) { + LOGD_IF(DEBUG_COPYBIT, "depth test and/or fog"); return false; } @@ -129,6 +137,7 @@ static bool checkContext(ogles_context_t* c) { EGLTextureObject* textureObject = u.texture; if (!supportedCopybitsFormat(textureObject->surface.format)) { + LOGD_IF(DEBUG_COPYBIT, "texture format not supported"); return false; } return true; @@ -161,19 +170,25 @@ static bool copybit(GLint x, GLint y, || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) { // The requested scale is out of the range the hardware // can support. + LOGD_IF(DEBUG_COPYBIT, + "scale out of range dsdx=%08x, dtdy=%08x", dsdx, dtdy); return false; } + /* int32_t texelArea = gglMulx(dtdy, dsdx); if (texelArea < FIXED_ONE && textureObject->mag_filter != GL_LINEAR) { // Non-linear filtering on a texture enlargement. + LOGD_IF(DEBUG_COPYBIT, "mag filter is not GL_LINEAR"); return false; } if (texelArea > FIXED_ONE && textureObject->min_filter != GL_LINEAR) { // Non-linear filtering on an texture shrink. + LOGD_IF(DEBUG_COPYBIT, "min filter is not GL_LINEAR"); return false; } + */ const uint32_t enables = c->rasterizer.state.enables; int planeAlpha = 255; @@ -192,6 +207,7 @@ static bool copybit(GLint x, GLint y, if (! (c->currentColorClamped.r == FIXED_ONE && c->currentColorClamped.g == FIXED_ONE && c->currentColorClamped.b == FIXED_ONE)) { + LOGD_IF(DEBUG_COPYBIT, "MODULATE and non white color"); return false; } planeAlpha = fixedToByte(c->currentColorClamped.a); @@ -199,6 +215,7 @@ static bool copybit(GLint x, GLint y, default: // Incompatible texture environment. + LOGD_IF(DEBUG_COPYBIT, "incompatible texture environment"); return false; } @@ -220,6 +237,7 @@ static bool copybit(GLint x, GLint y, && c->rasterizer.state.blend.dst == GL_ONE_MINUS_SRC_ALPHA && c->rasterizer.state.blend.alpha_separate == 0)) { // Incompatible blend mode. + LOGD_IF(DEBUG_COPYBIT, "incompatible blend mode"); return false; } blending = true; @@ -227,12 +245,14 @@ static bool copybit(GLint x, GLint y, // No blending is OK if we are not using alpha. if (srcTextureHasAlpha || planeAlpha != 255) { // Incompatible alpha + LOGD_IF(DEBUG_COPYBIT, "incompatible alpha"); return false; } } if (srcTextureHasAlpha && planeAlpha != 255) { // Can't do two types of alpha at once. + LOGD_IF(DEBUG_COPYBIT, "src alpha and plane alpha"); return false; } @@ -264,86 +284,116 @@ static bool copybit(GLint x, GLint y, /* * Try to draw a triangle fan with copybit, return false if we fail. */ -bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) { - if (! checkContext(c)) { +bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count) +{ + if (!checkContext(c)) { return false; } c->arrays.compileElements(c, c->vc.vBuffer, 0, 4); - // Is the result a screen aligned rectangle? - int sx[4]; - int sy[4]; - for (int i = 0; i < 4; i++) { - GLfixed x = c->vc.vBuffer[i].window.x; - GLfixed y = c->vc.vBuffer[i].window.y; - if (x < 0 || y < 0 || (x & 0xf) != 0 || (y & 0xf) != 0) { - return false; - } - sx[i] = x >> 4; - sy[i] = y >> 4; - } - /* - * This is the pattern we're looking for: - * (2)--(3) - * |\ | - * | \ | - * | \ | - * | \| - * (1)--(0) - * - */ - int dx[4]; - int dy[4]; - for (int i = 0; i < 4; i++) { - int i1 = (i + 1) & 3; - dx[i] = sx[i] - sx[i1]; - dy[i] = sy[i] - sy[i1]; + // we detect if we're dealing with a rectangle, by comparing the + // rectangles {v0,v2} and {v1,v3} which should be identical. + + const vec4_t& v0 = c->vc.vBuffer[0].window; + const vec4_t& v1 = c->vc.vBuffer[1].window; + const vec4_t& v2 = c->vc.vBuffer[2].window; + const vec4_t& v3 = c->vc.vBuffer[3].window; + int l = min(v0.x, v2.x); + int b = min(v0.y, v2.y); + int r = max(v0.x, v2.x); + int t = max(v0.y, v2.y); + if ((l != min(v1.x, v3.x)) || (b != min(v1.y, v3.y)) || + (r != max(v1.x, v3.x)) || (t != max(v1.y, v3.y))) { + LOGD_IF(DEBUG_COPYBIT, "geometry not a rectangle"); + return false; } - if (dx[1] | dx[3] | dy[0] | dy[2]) { + + const vec4_t& t0 = c->vc.vBuffer[0].texture[0]; + const vec4_t& t1 = c->vc.vBuffer[1].texture[0]; + const vec4_t& t2 = c->vc.vBuffer[2].texture[0]; + const vec4_t& t3 = c->vc.vBuffer[3].texture[0]; + int txl = min(t0.x, t2.x); + int txb = min(t0.y, t2.y); + int txr = max(t0.x, t2.x); + int txt = max(t0.y, t2.y); + if ((txl != min(t1.x, t3.x)) || (txb != min(t1.y, t3.y)) || + (txr != max(t1.x, t3.x)) || (txt != max(t1.y, t3.y))) { + LOGD_IF(DEBUG_COPYBIT, "texcoord not a rectangle"); return false; } - if (dx[0] != -dx[2] || dy[1] != -dy[3]) { + if ((txl != 0) || (txb != 0) || + (txr != FIXED_ONE) || (txt != FIXED_ONE)) { + // we could probably handle this case, if we wanted to + LOGD_IF(DEBUG_COPYBIT, "texture is cropped"); return false; } - int x = sx[1]; - int y = sy[1]; - int w = dx[0]; - int h = dy[3]; - - // We expect the texture coordinates to always be the unit square: + // at this point, we know we are dealing with a rectangle, so we + // only need to consider 3 vertices for computing the jacobians + + const int dx01 = v1.x - v0.x; + const int dy01 = v1.y - v0.y; + const int dx02 = v2.x - v0.x; + const int dy02 = v2.y - v0.y; + const int ds01 = t1.S - t0.S; + const int dt01 = t1.T - t0.T; + const int ds02 = t2.S - t0.S; + const int dt02 = t2.T - t0.T; + const int area = dx01*dy02 - dy01*dx02; + int dsdx, dsdy, dtdx, dtdy; + if (area >= 0) { + dsdx = ds01*dy02 - ds02*dy01; + dsdy = ds02*dx01 - ds01*dx02; + dtdx = dt01*dy02 - dt02*dy01; + dtdy = dt02*dx01 - dt01*dx02; + } else { + dsdx = ds02*dy01 - ds01*dy02; + dsdy = ds01*dx02 - ds02*dx01; + dtdx = dt02*dy01 - dt01*dy02; + dtdy = dt01*dx02 - dt02*dx01; + } - static const GLfixed kExpectedUV[8] = { - 0, 0, - 0, FIXED_ONE, - FIXED_ONE, FIXED_ONE, - FIXED_ONE, 0 - }; - { - const GLfixed* pExpected = &kExpectedUV[0]; - for (int i = 0; i < 4; i++) { - GLfixed u = c->vc.vBuffer[i].texture[0].x; - GLfixed v = c->vc.vBuffer[i].texture[0].y; - if (u != *pExpected++ || v != *pExpected++) { - return false; - } - } + // here we rely on the fact that we know the transform is + // a rigid-body transform AND that it can only rotate in 90 degrees + // increments + + int transform = 0; + if (dsdx == 0) { + // 90 deg rotation case + // [ 0 dtdx ] + // [ dsdx 0 ] + transform |= COPYBIT_TRANSFORM_ROT_90; + // FIXME: not sure if FLIP_H and FLIP_V shouldn't be inverted + if (dtdx > 0) + transform |= COPYBIT_TRANSFORM_FLIP_H; + if (dsdy < 0) + transform |= COPYBIT_TRANSFORM_FLIP_V; + } else { + // [ dsdx 0 ] + // [ 0 dtdy ] + if (dsdx < 0) + transform |= COPYBIT_TRANSFORM_FLIP_H; + if (dtdy < 0) + transform |= COPYBIT_TRANSFORM_FLIP_V; } - static const int tmu = 0; - texture_unit_t& u(c->textures.tmu[tmu]); - EGLTextureObject* textureObject = u.texture; + //LOGD("l=%d, b=%d, w=%d, h=%d, tr=%d", x, y, w, h, transform); + //LOGD("A=%f\tB=%f\nC=%f\tD=%f", + // dsdx/65536.0, dtdx/65536.0, dsdy/65536.0, dtdy/65536.0); + int x = l >> 4; + int y = b >> 4; + int w = (r-l) >> 4; + int h = (t-b) >> 4; + texture_unit_t& u(c->textures.tmu[0]); + EGLTextureObject* textureObject = u.texture; GLint tWidth = textureObject->surface.width; GLint tHeight = textureObject->surface.height; GLint crop_rect[4] = {0, tHeight, tWidth, -tHeight}; - const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; y = cbSurface.height - (y + h); - - return copybit(x, y, w, h, textureObject, crop_rect, - COPYBIT_TRANSFORM_ROT_90, c); + return copybit(x, y, w, h, textureObject, crop_rect, transform, c); } /* @@ -357,17 +407,12 @@ bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, if ((w|h) <= 0) { return true; } - - if (! checkContext(c)) { + if (!checkContext(c)) { return false; } - - static const int tmu = 0; - texture_unit_t& u(c->textures.tmu[tmu]); + texture_unit_t& u(c->textures.tmu[0]); EGLTextureObject* textureObject = u.texture; - - return copybit(x, y, w, h, textureObject, textureObject->crop_rect, - 0, c); + return copybit(x, y, w, h, textureObject, textureObject->crop_rect, 0, c); } } // namespace android diff --git a/opengl/libagl/copybit.h b/opengl/libagl/copybit.h index 401b68c2914a..b8b5afda2656 100644 --- a/opengl/libagl/copybit.h +++ b/opengl/libagl/copybit.h @@ -28,7 +28,8 @@ namespace android { bool drawTexiOESWithCopybit_impl(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c); -bool drawTrangleFanWithCopybit_impl(ogles_context_t* c, GLint first, + +bool drawTriangleFanWithCopybit_impl(ogles_context_t* c, GLint first, GLsizei count); inline bool copybitQuickCheckContext(ogles_context_t* c) { @@ -54,17 +55,16 @@ inline bool drawTexiOESWithCopybit(GLint x, GLint y, GLint z, * Tries to draw a triangle fan using copybit hardware. * Returns true if successful. */ -inline bool drawTrangleFanWithCopybit(ogles_context_t* c, GLint first, +inline bool drawTriangleFanWithCopybit(ogles_context_t* c, GLint first, GLsizei count) { /* * We are looking for the glDrawArrays call made by SurfaceFlinger. */ - if (!(copybitQuickCheckContext(c) && first == 0 && count == 4)) { + if ((count!=4) || first || !copybitQuickCheckContext(c)) return false; - } - return drawTrangleFanWithCopybit_impl(c, first, count); + return drawTriangleFanWithCopybit_impl(c, first, count); } -- cgit v1.2.3-59-g8ed1b