Integrate from //sandbox/mathias/donut/...@145728
SurfaceFlinger rework for new EGL driver model support.
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f944357..577dd4b 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -2,9 +2,9 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ BufferMapper.cpp \
Camera.cpp \
CameraParameters.cpp \
- EGLDisplaySurface.cpp \
EGLNativeWindowSurface.cpp \
EventHub.cpp \
EventRecurrence.cpp \
diff --git a/libs/ui/BufferMapper.cpp b/libs/ui/BufferMapper.cpp
new file mode 100644
index 0000000..a97188e
--- /dev/null
+++ b/libs/ui/BufferMapper.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 "BufferMapper"
+
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/Log.h>
+
+#include <ui/BufferMapper.h>
+#include <ui/Rect.h>
+
+#include <EGL/android_natives.h>
+
+#include <hardware/gralloc.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+BufferMapper::BufferMapper()
+ : mAllocMod(0)
+{
+ hw_module_t const* module;
+ int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
+ if (err == 0) {
+ mAllocMod = (gralloc_module_t const *)module;
+ }
+}
+
+status_t BufferMapper::map(buffer_handle_t handle, void** addr)
+{
+ Mutex::Autolock _l(mLock);
+ status_t err = mAllocMod->map(mAllocMod, handle, addr);
+ LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+ return err;
+}
+
+status_t BufferMapper::unmap(buffer_handle_t handle)
+{
+ Mutex::Autolock _l(mLock);
+ status_t err = mAllocMod->unmap(mAllocMod, handle);
+ LOGW_IF(err, "unmap(...) failed %d (%s)", err, strerror(-err));
+ return err;
+}
+
+status_t BufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds)
+{
+ status_t err = mAllocMod->lock(mAllocMod, handle, usage,
+ bounds.left, bounds.top, bounds.width(), bounds.height());
+ LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+ return err;
+}
+
+status_t BufferMapper::unlock(buffer_handle_t handle)
+{
+ status_t err = mAllocMod->unlock(mAllocMod, handle);
+ LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err));
+ return err;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp
deleted file mode 100644
index d06c98b..0000000
--- a/libs/ui/EGLDisplaySurface.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- **
- ** 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 "EGLDisplaySurface"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <hardware/copybit.h>
-
-#include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <ui/EGLDisplaySurface.h>
-
-#if HAVE_ANDROID_OS
-#include <linux/msm_mdp.h>
-#endif
-
-#include <EGL/egl.h>
-
-#include <pixelflinger/format.h>
-
-
-// ----------------------------------------------------------------------------
-
-egl_native_window_t* android_createDisplaySurface()
-{
- egl_native_window_t* s = new android::EGLDisplaySurface();
- s->memory_type = NATIVE_MEMORY_TYPE_GPU;
- return s;
-}
-
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-EGLDisplaySurface::EGLDisplaySurface()
- : EGLNativeSurface<EGLDisplaySurface>()
-{
- egl_native_window_t::version = sizeof(egl_native_window_t);
- egl_native_window_t::ident = 0;
- egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef;
- egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef;
- egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers;
- egl_native_window_t::connect = 0;
- egl_native_window_t::disconnect = 0;
-
- mFb[0].data = 0;
- mFb[1].data = 0;
- mBlitEngine = 0;
- egl_native_window_t::fd = mapFrameBuffer();
- if (egl_native_window_t::fd >= 0) {
-
- hw_module_t const* module;
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
- copybit_open(module, &mBlitEngine);
- }
-
- const float in2mm = 25.4f;
- float refreshRate = 1000000000000000LLU / (
- float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres )
- * ( mInfo.left_margin + mInfo.right_margin + mInfo.xres )
- * mInfo.pixclock);
-
- const GGLSurface& buffer = mFb[1 - mIndex];
- egl_native_window_t::width = buffer.width;
- egl_native_window_t::height = buffer.height;
- egl_native_window_t::stride = buffer.stride;
- egl_native_window_t::format = buffer.format;
- egl_native_window_t::base = intptr_t(mFb[0].data);
- egl_native_window_t::offset =
- intptr_t(buffer.data) - egl_native_window_t::base;
- egl_native_window_t::flags = 0;
- egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width;
- egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height;
- egl_native_window_t::fps = refreshRate;
- egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB;
- // no error, set the magic word
- egl_native_window_t::magic = 0x600913;
- }
- mSwapCount = -1;
- mPageFlipCount = 0;
-}
-
-EGLDisplaySurface::~EGLDisplaySurface()
-{
- magic = 0;
- copybit_close(mBlitEngine);
- mBlitEngine = 0;
- close(egl_native_window_t::fd);
- munmap(mFb[0].data, mSize);
- if (!(mFlags & PAGE_FLIP))
- free((void*)mFb[1].data);
-}
-
-void EGLDisplaySurface::hook_incRef(NativeWindowType window) {
- EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
- that->incStrong(that);
-}
-void EGLDisplaySurface::hook_decRef(NativeWindowType window) {
- EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
- that->decStrong(that);
-}
-uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) {
- EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window);
- return that->swapBuffers();
-}
-
-void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h)
-{
- mInfo.reserved[0] = 0x54445055; // "UPDT";
- mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
- mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
-}
-
-uint32_t EGLDisplaySurface::swapBuffers()
-{
-#define SHOW_FPS 0
-#if SHOW_FPS
- nsecs_t now = systemTime();
- if (mSwapCount == -1) {
- mTime = now;
- mSwapCount = 0;
- mSleep = 0;
- } else {
- nsecs_t d = now-mTime;
- if (d >= seconds(1)) {
- double fps = (mSwapCount * double(seconds(1))) / double(d);
- LOGD("%f fps, sleep=%d / frame",
- fps, (int)ns2us(mSleep / mSwapCount));
- mSwapCount = 0;
- mTime = now;
- mSleep = 0;
- } else {
- mSwapCount++;
- }
- }
-#endif
- /* If we can't do the page_flip, just copy the back buffer to the front */
- if (!(mFlags & PAGE_FLIP)) {
- memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);
- return 0;
- }
-
- // do the actual flip
- mIndex = 1 - mIndex;
- mInfo.activate = FB_ACTIVATE_VBL;
- mInfo.yoffset = mIndex ? mInfo.yres : 0;
- if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) {
- LOGE("FBIOPUT_VSCREENINFO failed");
- return 0;
- }
-
- /*
- * this is a monstrous hack: Because the h/w accelerator is not able
- * to render directly into the framebuffer, we need to copy its
- * internal framebuffer out to the fb.
- * oem[0] is used to access the fd of internal fb.
- * All this is needed only in standalone mode, in SurfaceFlinger mode
- * we control where the GPU renders.
- * We do this only if we have copybit, since this hack is needed only
- * with msm7k.
- */
- if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0] && mBlitEngine) {
- copybit_device_t *copybit = mBlitEngine;
- copybit_rect_t sdrect = { 0, 0,
- egl_native_window_t::width, egl_native_window_t::height };
- copybit_image_t dst = {
- egl_native_window_t::width,
- egl_native_window_t::height,
- egl_native_window_t::format,
- egl_native_window_t::offset,
- (void*)egl_native_window_t::base,
- egl_native_window_t::fd
- };
- copybit_image_t src = {
- egl_native_window_t::width,
- egl_native_window_t::height,
- egl_native_window_t::format, // XXX: use proper format
- egl_native_window_t::offset,
- (void*)egl_native_window_t::base, // XXX: use proper base
- egl_native_window_t::oem[0]
- };
- region_iterator it(Region(Rect(
- egl_native_window_t::width, egl_native_window_t::height)));
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
- copybit->stretch(copybit, &dst, &src, &sdrect, &sdrect, &it);
- }
-
- // update the address of the buffer to draw to next
- const GGLSurface& buffer = mFb[1 - mIndex];
- egl_native_window_t::offset =
- intptr_t(buffer.data) - egl_native_window_t::base;
-
-#if SHOW_FPS
- mSleep += systemTime()-now;
-#endif
-
- mPageFlipCount++;
-
- // We don't support screen-size changes for now
- return 0;
-}
-
-int32_t EGLDisplaySurface::getPageFlipCount() const
-{
- return mPageFlipCount;
-}
-
-void EGLDisplaySurface::copyFrontToBack(const Region& copyback)
-{
-#if HAVE_ANDROID_OS
- if (mBlitEngine) {
- copybit_image_t dst = {
- w: egl_native_window_t::stride,
- h: egl_native_window_t::height,
- format: egl_native_window_t::format,
- offset: mFb[1-mIndex].data - mFb[0].data,
- base: (void*)egl_native_window_t::base,
- fd: egl_native_window_t::fd
- };
- copybit_image_t src = {
- w: egl_native_window_t::stride,
- h: egl_native_window_t::height,
- format: egl_native_window_t::format,
- offset: mFb[mIndex].data - mFb[0].data,
- base: (void*)egl_native_window_t::base,
- fd: egl_native_window_t::fd
- };
- region_iterator it(copyback);
- mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
- } else
-#endif
- {
- /* no extra copy needed since we copied back to front instead of
- * flipping */
- if (!(mFlags & PAGE_FLIP)) {
- return;
- }
-
- Region::iterator iterator(copyback);
- if (iterator) {
- Rect r;
- uint8_t* const screen_src = mFb[ mIndex].data;
- uint8_t* const screen_dst = mFb[1-mIndex].data;
- const size_t bpp = bytesPerPixel(egl_native_window_t::format);
- const size_t bpr = egl_native_window_t::stride * bpp;
- while (iterator.iterate(&r)) {
- ssize_t h = r.bottom - r.top;
- if (h) {
- size_t size = (r.right - r.left) * bpp;
- size_t o = (r.left + egl_native_window_t::stride * r.top) * bpp;
- uint8_t* s = screen_src + o;
- uint8_t* d = screen_dst + o;
- if (size == bpr) {
- size *= h;
- h = 1;
- }
- do {
- memcpy(d, s, size);
- d += bpr;
- s += bpr;
- } while (--h > 0);
- }
- }
- }
- }
-}
-
-void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst)
-{
-#if HAVE_ANDROID_OS
- if (mBlitEngine) {
- copybit_image_t src = {
- w: egl_native_window_t::stride,
- h: egl_native_window_t::height,
- format: egl_native_window_t::format,
- offset: mFb[mIndex].data - mFb[0].data,
- base: (void*)egl_native_window_t::base,
- fd: egl_native_window_t::fd
- };
- region_iterator it(Region(Rect(
- egl_native_window_t::width, egl_native_window_t::height)));
- mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
- } else
-#endif
- {
- uint8_t* const screen_src = mFb[ mIndex].data;
- const size_t bpp = bytesPerPixel(egl_native_window_t::format);
- const size_t bpr = egl_native_window_t::stride * bpp;
- memcpy((char*)dst.base + dst.offset, screen_src,
- bpr*egl_native_window_t::height);
- }
-}
-
-void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst)
-{
-#if HAVE_ANDROID_OS
- if (mBlitEngine) {
- copybit_image_t src = {
- w: egl_native_window_t::stride,
- h: egl_native_window_t::height,
- format: egl_native_window_t::format,
- offset: mFb[1-mIndex].data - mFb[0].data,
- base: (void*)egl_native_window_t::base,
- fd: egl_native_window_t::fd
- };
- region_iterator it(Region(Rect(
- egl_native_window_t::width, egl_native_window_t::height)));
- mBlitEngine->blit(mBlitEngine, &dst, &src, &it);
- } else
-#endif
- {
- uint8_t* const screen_src = mFb[1-mIndex].data;
- const size_t bpp = bytesPerPixel(egl_native_window_t::format);
- const size_t bpr = egl_native_window_t::stride * bpp;
- memcpy((char*)dst.base + dst.offset, screen_src,
- bpr*egl_native_window_t::height);
- }
-}
-
-
-status_t EGLDisplaySurface::mapFrameBuffer()
-{
- char const * const device_template[] = {
- "/dev/graphics/fb%u",
- "/dev/fb%u",
- 0 };
- int fd = -1;
- int i=0;
- char name[64];
- while ((fd==-1) && device_template[i]) {
- snprintf(name, 64, device_template[i], 0);
- fd = open(name, O_RDWR, 0);
- i++;
- }
- if (fd < 0)
- return -errno;
-
- struct fb_fix_screeninfo finfo;
- if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
- return -errno;
-
- struct fb_var_screeninfo info;
- if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
- return -errno;
-
- info.reserved[0] = 0;
- info.reserved[1] = 0;
- info.reserved[2] = 0;
- info.xoffset = 0;
- info.yoffset = 0;
- info.yres_virtual = info.yres * 2;
- info.bits_per_pixel = 16;
- /* Explicitly request 5/6/5 */
- info.red.offset = 11;
- info.red.length = 5;
- info.green.offset = 5;
- info.green.length = 6;
- info.blue.offset = 0;
- info.blue.length = 5;
- info.transp.offset = 0;
- info.transp.length = 0;
- info.activate = FB_ACTIVATE_NOW;
-
- uint32_t flags = PAGE_FLIP;
- if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
- info.yres_virtual = info.yres;
- flags &= ~PAGE_FLIP;
- LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
- }
-
- if (info.yres_virtual < info.yres * 2) {
- info.yres_virtual = info.yres;
- flags &= ~PAGE_FLIP;
- LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
- info.yres_virtual, info.yres*2);
- }
-
- if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
- return -errno;
-
- int refreshRate = 1000000000000000LLU /
- (
- uint64_t( info.upper_margin + info.lower_margin + info.yres )
- * ( info.left_margin + info.right_margin + info.xres )
- * info.pixclock
- );
-
- if (refreshRate == 0) {
- // bleagh, bad info from the driver
- refreshRate = 60*1000; // 60 Hz
- }
- if (int(info.width) <= 0 || int(info.height) <= 0) {
- // the driver doesn't return that information
- // default to 160 dpi
- info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
- info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
- }
-
- float xdpi = (info.xres * 25.4f) / info.width;
- float ydpi = (info.yres * 25.4f) / info.height;
- float fps = refreshRate / 1000.0f;
-
- LOGI( "using (fd=%d)\n"
- "id = %s\n"
- "xres = %d px\n"
- "yres = %d px\n"
- "xres_virtual = %d px\n"
- "yres_virtual = %d px\n"
- "bpp = %d\n"
- "r = %2u:%u\n"
- "g = %2u:%u\n"
- "b = %2u:%u\n",
- fd,
- finfo.id,
- info.xres,
- info.yres,
- info.xres_virtual,
- info.yres_virtual,
- info.bits_per_pixel,
- info.red.offset, info.red.length,
- info.green.offset, info.green.length,
- info.blue.offset, info.blue.length
- );
-
- LOGI( "width = %d mm (%f dpi)\n"
- "height = %d mm (%f dpi)\n"
- "refresh rate = %.2f Hz\n",
- info.width, xdpi,
- info.height, ydpi,
- fps
- );
-
-
- if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
- return -errno;
-
- if (finfo.smem_len <= 0)
- return -errno;
-
- /*
- * Open and map the display.
- */
-
- void* buffer = (uint16_t*) mmap(
- 0, finfo.smem_len,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fd, 0);
-
- if (buffer == MAP_FAILED)
- return -errno;
-
- // at least for now, always clear the fb
- memset(buffer, 0, finfo.smem_len);
-
- uint8_t* offscreen[2];
- offscreen[0] = (uint8_t*)buffer;
- if (flags & PAGE_FLIP) {
- offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres;
- } else {
- offscreen[1] = (uint8_t*)malloc(finfo.smem_len);
- if (offscreen[1] == 0) {
- munmap(buffer, finfo.smem_len);
- return NO_MEMORY;
- }
- }
-
- mFlags = flags;
- mInfo = info;
- mFinfo = finfo;
- mSize = finfo.smem_len;
- mIndex = 0;
- for (int i=0 ; i<2 ; i++) {
- mFb[i].version = sizeof(GGLSurface);
- mFb[i].width = info.xres;
- mFb[i].height = info.yres;
- mFb[i].stride = finfo.line_length / (info.bits_per_pixel >> 3);
- mFb[i].data = (GGLubyte*)(offscreen[i]);
- mFb[i].format = GGL_PIXEL_FORMAT_RGB_565;
- }
- return fd;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp
index f1071cf..5d9d6a4 100644
--- a/libs/ui/EGLNativeWindowSurface.cpp
+++ b/libs/ui/EGLNativeWindowSurface.cpp
@@ -20,142 +20,225 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
+#include <utils/threads.h>
#include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
#include <ui/Rect.h>
+#include <ui/EGLNativeWindowSurface.h>
#include <EGL/egl.h>
#include <pixelflinger/format.h>
+#include <pixelflinger/pixelflinger.h>
-#include <ui/EGLNativeWindowSurface.h>
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
-EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface)
- : EGLNativeSurface<EGLNativeWindowSurface>(),
- mSurface(surface), mConnected(false)
-{
- egl_native_window_t::magic = 0x600913;
- egl_native_window_t::version = sizeof(egl_native_window_t);
- egl_native_window_t::ident = 0;
- egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef;
- egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef;
- egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers;
- egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect;
- egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect;
-
- DisplayInfo dinfo;
- SurfaceComposerClient::getDisplayInfo(0, &dinfo);
- egl_native_window_t::xdpi = dinfo.xdpi;
- egl_native_window_t::ydpi = dinfo.ydpi;
- egl_native_window_t::fps = dinfo.fps;
- egl_native_window_t::flags= EGL_NATIVES_FLAG_DESTROY_BACKBUFFER;
-}
+/*
+ * 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).
+ *
+ */
-EGLNativeWindowSurface::~EGLNativeWindowSurface()
+FramebufferNativeWindow::FramebufferNativeWindow()
+ : BASE(), fbDev(0), grDev(0)
{
- disconnect();
- mSurface.clear();
- magic = 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;
-void EGLNativeWindowSurface::hook_incRef(NativeWindowType window)
-{
- EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
- that->incStrong(that);
-}
+
+ // 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);
-void EGLNativeWindowSurface::hook_decRef(NativeWindowType window)
-{
- EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
- that->decStrong(that);
-}
+ LOGE_IF(err, "fb buffer 0 allocation failed w=%d, h=%d, err=%s",
+ fbDev->width, fbDev->height, strerror(-err));
-void EGLNativeWindowSurface::hook_connect(NativeWindowType window)
-{
- EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
- that->connect();
-}
+ err = grDev->alloc(grDev,
+ fbDev->width, fbDev->height, fbDev->format,
+ GRALLOC_USAGE_HW_FB, &buffers[1]->handle, &buffers[1]->stride);
-void EGLNativeWindowSurface::hook_disconnect(NativeWindowType window)
-{
- EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
- that->disconnect();
-}
+ LOGE_IF(err, "fb buffer 1 allocation failed w=%d, h=%d, err=%s",
+ fbDev->width, fbDev->height, strerror(-err));
-uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window)
-{
- EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window);
- return that->swapBuffers();
-}
+ gralloc_module_t* m =
+ reinterpret_cast<gralloc_module_t*>(grDev->common.module);
-void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h)
-{
- mSurface->setSwapRectangle(Rect(l, t, l+w, t+h));
-}
-
-uint32_t EGLNativeWindowSurface::swapBuffers()
-{
- const int w = egl_native_window_t::width;
- const int h = egl_native_window_t::height;
- const sp<Surface>& surface(mSurface);
- Surface::SurfaceInfo info;
- surface->unlockAndPost();
- surface->lock(&info);
- // update the address of the buffer to draw to next
- egl_native_window_t::base = intptr_t(info.base);
- egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
-
- // update size if it changed
- if (w != int(info.w) || h != int(info.h)) {
- egl_native_window_t::width = info.w;
- egl_native_window_t::height = info.h;
- egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
- egl_native_window_t::format = info.format;
- return EGL_NATIVES_FLAG_SIZE_CHANGED;
+ // 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<uint32_t&>(android_native_window_t::flags) = flags;
+ const_cast<float&>(android_native_window_t::xdpi) = fbDev->xdpi;
+ const_cast<float&>(android_native_window_t::ydpi) = fbDev->ydpi;
+ const_cast<int&>(android_native_window_t::minSwapInterval) =
+ fbDev->minSwapInterval;
+ const_cast<int&>(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<gralloc_module_t*>(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;
}
-void EGLNativeWindowSurface::connect()
-{
- if (!mConnected) {
- Surface::SurfaceInfo info;
- mSurface->lock(&info);
- mSurface->setSwapRectangle(Rect(info.w, info.h));
- mConnected = true;
+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;
- egl_native_window_t::width = info.w;
- egl_native_window_t::height = info.h;
- egl_native_window_t::stride = info.bpr / bytesPerPixel(info.format);
- egl_native_window_t::format = info.format;
- egl_native_window_t::base = intptr_t(info.base);
- egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base);
- // FIXME: egl_native_window_t::memory_type used to be set from
- // mSurface, but we wanted to break this dependency. We set it to
- // GPU because the software rendered doesn't care, but the h/w
- // accelerator needs it. Eventually, this value should go away
- // completely, since memory will be managed by OpenGL.
- egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_GPU;
- egl_native_window_t::fd = 0;
+ // 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;
}
-void EGLNativeWindowSurface::disconnect()
+int FramebufferNativeWindow::lockBuffer(android_native_window_t* window,
+ android_native_buffer_t* buffer)
{
- if (mConnected) {
- mSurface->unlock();
- mConnected = false;
+ 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<gralloc_module_t*>(self->grDev->common.module);
+ const Rect& dirty(self->mDirty);
+
+ buffer_handle_t handle = static_cast<NativeBuffer*>(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<gralloc_module_t*>(self->grDev->common.module);
+
+ buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
+ m->unlock(m, handle);
+ int res = fb->post(fb, handle);
+
+ self->front = static_cast<NativeBuffer*>(buffer);
+ self->mNumFreeBuffers++;
+ self->mCondition.broadcast();
+ return res;
}
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
+
+
+EGLNativeWindowType android_createDisplaySurface(void)
+{
+ return new android::FramebufferNativeWindow();
+}
+
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index d5e9f81..fcea8ec 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "ISurface"
+
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
@@ -23,10 +25,13 @@
#include <ui/ISurface.h>
#include <ui/Overlay.h>
+#include <ui/Surface.h>
namespace android {
+// ----------------------------------------------------------------------
+
ISurface::BufferHeap::BufferHeap()
: w(0), h(0), hor_stride(0), ver_stride(0), format(0),
transform(0), flags(0)
@@ -55,6 +60,8 @@
{
}
+// ----------------------------------------------------------------------
+
class BpSurface : public BpInterface<ISurface>
{
public:
@@ -63,6 +70,15 @@
{
}
+ virtual sp<SurfaceBuffer> getBuffer()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+ remote()->transact(GET_BUFFER, data, &reply);
+ sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
+ return buffer;
+ }
+
virtual status_t registerBuffers(const BufferHeap& buffers)
{
Parcel data, reply;
@@ -122,6 +138,11 @@
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
+ case GET_BUFFER: {
+ CHECK_INTERFACE(ISurface, data, reply);
+ sp<SurfaceBuffer> buffer(getBuffer());
+ return SurfaceBuffer::writeToParcel(reply, buffer.get());
+ }
case REGISTER_BUFFERS: {
CHECK_INTERFACE(ISurface, data, reply);
BufferHeap buffer;
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/ui/ISurfaceComposer.cpp
index 76597e1..1932bf9 100644
--- a/libs/ui/ISurfaceComposer.cpp
+++ b/libs/ui/ISurfaceComposer.cpp
@@ -114,36 +114,6 @@
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t requestGPU(
- const sp<IGPUCallback>& callback, gpu_info_t* gpu)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(callback->asBinder());
- remote()->transact(BnSurfaceComposer::REQUEST_GPU, data, &reply);
- gpu->regs = interface_cast<IMemory>(reply.readStrongBinder());
- gpu->count = reply.readInt32();
-
- // FIXME: for now, we don't dynamically allocate the regions array
- size_t maxCount = sizeof(gpu->regions)/sizeof(*gpu->regions);
- if (gpu->count > maxCount)
- return BAD_VALUE;
-
- for (size_t i=0 ; i<gpu->count ; i++) {
- gpu->regions[i].region = interface_cast<IMemory>(reply.readStrongBinder());
- gpu->regions[i].reserved = reply.readInt32();
- }
- return reply.readInt32();
- }
-
- virtual status_t revokeGPU()
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::REVOKE_GPU, data, &reply);
- return reply.readInt32();
- }
-
virtual void signal() const
{
Parcel data, reply;
@@ -201,9 +171,6 @@
case BOOT_FINISHED: {
bootFinished();
} break;
- case REVOKE_GPU: {
- reply->writeInt32( revokeGPU() );
- } break;
case SIGNAL: {
signal();
} break;
@@ -211,26 +178,6 @@
sp<IBinder> b = getCblk()->asBinder();
reply->writeStrongBinder(b);
} break;
- case REQUEST_GPU: {
- // TODO: this should be protected by a permission
- gpu_info_t info;
- sp<IGPUCallback> callback
- = interface_cast<IGPUCallback>(data.readStrongBinder());
- status_t res = requestGPU(callback, &info);
-
- // FIXME: for now, we don't dynamically allocate the regions array
- size_t maxCount = sizeof(info.regions)/sizeof(*info.regions);
- if (info.count > maxCount)
- return BAD_VALUE;
-
- reply->writeStrongBinder(info.regs->asBinder());
- reply->writeInt32(info.count);
- for (size_t i=0 ; i<info.count ; i++) {
- reply->writeStrongBinder(info.regions[i].region->asBinder());
- reply->writeInt32(info.regions[i].reserved);
- }
- reply->writeInt32(res);
- } break;
default:
return UNKNOWN_TRANSACTION;
}
@@ -239,41 +186,4 @@
// ----------------------------------------------------------------------------
-enum {
- // Note: BOOT_FINISHED must remain this value, it is called by ActivityManagerService.
- GPU_LOST = IBinder::FIRST_CALL_TRANSACTION
-};
-
-class BpGPUCallback : public BpInterface<IGPUCallback>
-{
-public:
- BpGPUCallback(const sp<IBinder>& impl)
- : BpInterface<IGPUCallback>(impl)
- {
- }
-
- virtual void gpuLost()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IGPUCallback::getInterfaceDescriptor());
- remote()->transact(GPU_LOST, data, &reply, IBinder::FLAG_ONEWAY);
- }
-};
-
-IMPLEMENT_META_INTERFACE(GPUCallback, "android.ui.IGPUCallback");
-
-status_t BnGPUCallback::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case GPU_LOST: {
- CHECK_INTERFACE(IGPUCallback, data, reply);
- gpuLost();
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
};
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index dd6a798..597b87e 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -191,8 +191,6 @@
{
token = parcel.readInt32();
identity = parcel.readInt32();
- heap[0] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
- heap[1] = interface_cast<IMemoryHeap>(parcel.readStrongBinder());
return NO_ERROR;
}
@@ -200,8 +198,6 @@
{
parcel->writeInt32(token);
parcel->writeInt32(identity);
- parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
- parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
return NO_ERROR;
}
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index b236edc..59c6514 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -129,12 +129,8 @@
OverlayRef::~OverlayRef()
{
if (mOwnHandle) {
- /* FIXME: handles should be promoted to "real" API and be handled by
- * the framework */
- for (int i=0 ; i<mOverlayHandle->numFds ; i++) {
- close(mOverlayHandle->data[i]);
- }
- free((void*)mOverlayHandle);
+ native_handle_close(mOverlayHandle);
+ native_handle_delete(const_cast<native_handle*>(mOverlayHandle));
}
}
@@ -147,7 +143,7 @@
uint32_t f = data.readInt32();
uint32_t ws = data.readInt32();
uint32_t hs = data.readInt32();
- native_handle* handle = data.readNativeHandle(NULL, NULL);
+ native_handle* handle = data.readNativeHandle();
result = new OverlayRef();
result->mOverlayHandle = handle;
@@ -169,7 +165,7 @@
reply->writeInt32(o->mFormat);
reply->writeInt32(o->mWidthStride);
reply->writeInt32(o->mHeightStride);
- reply->writeNativeHandle(*(o->mOverlayHandle));
+ reply->writeNativeHandle(o->mOverlayHandle);
} else {
reply->writeStrongBinder(NULL);
}
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4ea9ae2..357e4d0 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -23,24 +23,126 @@
#include <sys/types.h>
#include <sys/stat.h>
-#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/IPCThreadState.h>
#include <utils/IMemory.h>
#include <utils/Log.h>
+#include <ui/DisplayInfo.h>
+#include <ui/BufferMapper.h>
+#include <ui/EGLNativeWindowSurface.h>
#include <ui/ISurface.h>
#include <ui/Surface.h>
#include <ui/SurfaceComposerClient.h>
#include <ui/Rect.h>
+#include <EGL/android_natives.h>
+
#include <private/ui/SharedState.h>
#include <private/ui/LayerState.h>
+#include <pixelflinger/pixelflinger.h>
+
namespace android {
-// ---------------------------------------------------------------------------
+// ============================================================================
+// SurfaceBuffer
+// ============================================================================
+
+SurfaceBuffer::SurfaceBuffer()
+ : BASE(), handle(0), mOwner(false)
+{
+ width =
+ height =
+ stride =
+ format =
+ usage = 0;
+ android_native_buffer_t::getHandle = getHandle;
+}
+
+SurfaceBuffer::SurfaceBuffer(const Parcel& data)
+ : BASE(), handle(0), mOwner(true)
+{
+ // we own the handle in this case
+ width = data.readInt32();
+ height = data.readInt32();
+ stride = data.readInt32();
+ format = data.readInt32();
+ usage = data.readInt32();
+ handle = data.readNativeHandle();
+ android_native_buffer_t::getHandle = getHandle;
+}
+
+SurfaceBuffer::~SurfaceBuffer()
+{
+ if (handle && mOwner) {
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle*>(handle));
+ }
+}
+
+int SurfaceBuffer::getHandle(android_native_buffer_t const * base,
+ buffer_handle_t* handle)
+{
+ *handle = getSelf(base)->handle;
+ return 0;
+}
+
+status_t SurfaceBuffer::writeToParcel(Parcel* reply,
+ android_native_buffer_t const* buffer)
+{
+ buffer_handle_t handle;
+ status_t err = buffer->getHandle(buffer, &handle);
+ if (err < 0) {
+ return err;
+ }
+ reply->writeInt32(buffer->width);
+ reply->writeInt32(buffer->height);
+ reply->writeInt32(buffer->stride);
+ reply->writeInt32(buffer->format);
+ reply->writeInt32(buffer->usage);
+ reply->writeNativeHandle(handle);
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------
+
+static void copyBlt(const android_native_buffer_t* dst,
+ const android_native_buffer_t* src, const Region& reg)
+{
+ Region::iterator iterator(reg);
+ if (iterator) {
+ // NOTE: dst and src must be the same format
+ Rect r;
+ 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);
+ }
+ }
+ }
+}
+
+// ============================================================================
+// Surface
+// ============================================================================
Surface::Surface(const sp<SurfaceComposerClient>& client,
const sp<ISurface>& surface,
@@ -51,26 +153,44 @@
mToken(data.token), mIdentity(data.identity),
mFormat(format), mFlags(flags), mOwner(owner)
{
+ 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();
- mSurfaceHeapBase[0] = 0;
- mSurfaceHeapBase[1] = 0;
- mHeap[0] = data.heap[0];
- mHeap[1] = data.heap[1];
+
+ DisplayInfo dinfo;
+ SurfaceComposerClient::getDisplayInfo(0, &dinfo);
+ const_cast<float&>(android_native_window_t::xdpi) = dinfo.xdpi;
+ const_cast<float&>(android_native_window_t::ydpi) = dinfo.ydpi;
+ // FIXME: set real values here
+ const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
+ const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
+ const_cast<uint32_t&>(android_native_window_t::flags) = 0;
}
Surface::Surface(Surface const* rhs)
: mOwner(false)
{
- mToken = rhs->mToken;
- mIdentity= rhs->mIdentity;
- mClient = rhs->mClient;
- mSurface = rhs->mSurface;
- mHeap[0] = rhs->mHeap[0];
- mHeap[1] = rhs->mHeap[1];
- mFormat = rhs->mFormat;
- mFlags = rhs->mFlags;
- mSurfaceHeapBase[0] = rhs->mSurfaceHeapBase[0];
- mSurfaceHeapBase[1] = rhs->mSurfaceHeapBase[1];
+ // FIXME: we really should get rid of this ctor. the memcpy below
+ //should be safe for now, but android_native_window_t is not supposed
+ // to be clonable.
+ memcpy( static_cast<android_native_window_t*>(this),
+ static_cast<android_native_window_t const *>(rhs),
+ sizeof(android_native_window_t));
+
+ mToken = rhs->mToken;
+ mIdentity = rhs->mIdentity;
+ mClient = rhs->mClient;
+ mSurface = rhs->mSurface;
+ mBuffers[0] = rhs->mBuffers[0];
+ mBuffers[1] = rhs->mBuffers[1];
+ mFormat = rhs->mFormat;
+ mFlags = rhs->mFlags;
mSwapRectangle.makeInvalid();
}
@@ -78,21 +198,26 @@
{
if (mOwner && mToken>=0 && mClient!=0) {
mClient->destroySurface(mToken);
+ if (mBuffers[0] != 0) {
+ BufferMapper::get().unmap(mBuffers[0]->getHandle());
+ }
+ if (mBuffers[1] != 0) {
+ BufferMapper::get().unmap(mBuffers[1]->getHandle());
+ }
}
mClient.clear();
mSurface.clear();
- mHeap[0].clear();
- mHeap[1].clear();
IPCThreadState::self()->flushCommands();
}
sp<Surface> Surface::dup() const
{
+ // FIXME: we should get rid of Surface::dup()
Surface const * r = this;
if (this && mOwner) {
// the only reason we need to do this is because of Java's garbage
// collector: because we're creating a copy of the Surface
- // instead of a reference, we can garantee that when our last
+ // instead of a reference, we can guarantee that when our last
// reference goes away, the real surface will be deleted.
// Without this hack (the code is correct too), we'd have to
// wait for a GC for the surface to go away.
@@ -101,31 +226,244 @@
return const_cast<Surface*>(r);
}
-status_t Surface::nextBuffer(SurfaceInfo* info) {
- return mClient->nextBuffer(this, info);
+status_t Surface::validate(per_client_cblk_t const* cblk) const
+{
+ if (cblk == 0) {
+ LOGE("cblk is null (surface id=%d, identity=%u)", mToken, mIdentity);
+ return NO_INIT;
+ }
+ status_t err = cblk->validate(mToken);
+ if (err != NO_ERROR) {
+ LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
+ mToken, mIdentity, err, strerror(-err));
+ return err;
+ }
+ if (mIdentity != uint32_t(cblk->layers[mToken].identity)) {
+ LOGE("using an invalid surface id=%d, identity=%u should be %d",
+ mToken, mIdentity, cblk->layers[mToken].identity);
+ return NO_INIT;
+ }
+ return NO_ERROR;
}
+// ----------------------------------------------------------------------------
+
+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;
+}
+
+int Surface::dequeueBuffer(android_native_window_t* window,
+ android_native_buffer_t** buffer)
+{
+ Surface* self = getSelf(window);
+ return self->dequeueBuffer(buffer);
+}
+
+int Surface::lockBuffer(android_native_window_t* window,
+ android_native_buffer_t* buffer)
+{
+ Surface* self = getSelf(window);
+ return self->lockBuffer(buffer);
+}
+
+int Surface::queueBuffer(android_native_window_t* window,
+ android_native_buffer_t* buffer)
+{
+ Surface* self = getSelf(window);
+ return self->queueBuffer(buffer);
+}
+
+// ----------------------------------------------------------------------------
+
+int Surface::dequeueBuffer(android_native_buffer_t** buffer)
+{
+ // FIXME: dequeueBuffer() needs proper implementation
+
+ Mutex::Autolock _l(mSurfaceLock);
+
+ per_client_cblk_t* const cblk = mClient->mControl;
+ status_t err = validate(cblk);
+ if (err != NO_ERROR)
+ return err;
+
+ SurfaceID index(mToken);
+
+ int32_t backIdx = cblk->lock_layer(size_t(index),
+ per_client_cblk_t::BLOCKING);
+
+ if (backIdx < 0)
+ return status_t(backIdx);
+
+ mBackbufferIndex = backIdx;
+ layer_cblk_t* const lcblk = &(cblk->layers[index]);
+
+ volatile const surface_info_t* const back = lcblk->surface + backIdx;
+ if (back->flags & surface_info_t::eNeedNewBuffer) {
+ getBufferLocked(backIdx);
+ }
+
+ const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+ *buffer = backBuffer.get();
+
+ return NO_ERROR;
+}
+
+int Surface::lockBuffer(android_native_buffer_t* buffer)
+{
+ // FIXME: lockBuffer() needs proper implementation
+ return 0;
+}
+
+int Surface::queueBuffer(android_native_buffer_t* buffer)
+{
+ Mutex::Autolock _l(mSurfaceLock);
+
+ per_client_cblk_t* const cblk = mClient->mControl;
+ status_t err = validate(cblk);
+ if (err != NO_ERROR)
+ return err;
+
+ // transmit the dirty region
+ const Region dirty(swapRectangle());
+ SurfaceID index(mToken);
+ layer_cblk_t* const lcblk = &(cblk->layers[index]);
+ _send_dirty_region(lcblk, dirty);
+
+ uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
+ if (!(newstate & eNextFlipPending))
+ mClient->signalServer();
+
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
return Surface::lock(info, NULL, blocking);
}
-status_t Surface::lock(SurfaceInfo* info, Region* dirty, bool blocking) {
- if (heapBase(0) == 0) return INVALID_OPERATION;
- if (heapBase(1) == 0) return INVALID_OPERATION;
- return mClient->lockSurface(this, info, dirty, blocking);
+status_t Surface::lock(SurfaceInfo* other, Region* dirty, bool blocking)
+{
+ // FIXME: needs some locking here
+ android_native_buffer_t* 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;
+
+ per_client_cblk_t* const cblk = mClient->mControl;
+ layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
+ volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
+ if (back->flags & surface_info_t::eBufferDirty) {
+ // 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;
+ if (!(lcblk->flags & eNoCopyBack)) {
+ const Region previousDirtyRegion(dirtyRegion());
+ copyback = previousDirtyRegion.subtract(newDirtyRegion);
+ }
+ const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
+ if (!copyback.isEmpty() && frontBuffer!=0) {
+ // copy front to back
+ copyBlt(backBuffer, frontBuffer.get(), copyback);
+ }
+ }
+ setDirtyRegion(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);
+ LOGW_IF(res, "failed locking buffer %d (%p)",
+ mBackbufferIndex, handle);
+ setSwapRectangle(lockBounds);
+ }
+ }
+ return err;
+}
+
+status_t Surface::unlockAndPost()
+{
+ // FIXME: needs some locking here
+
+ if (mLockedBuffer == 0)
+ return BAD_VALUE;
+
+ buffer_handle_t handle;
+ mLockedBuffer->getHandle(mLockedBuffer, &handle);
+ status_t res = BufferMapper::get().unlock(handle);
+ LOGW_IF(res, "failed unlocking buffer %d (%p)",
+ mBackbufferIndex, handle);
+
+ const Rect dirty(dirtyRegion().bounds());
+ setSwapRectangle(dirty);
+ status_t err = queueBuffer(mLockedBuffer);
+ mLockedBuffer->common.decRef(&mLockedBuffer->common);
+ mLockedBuffer = 0;
+ return err;
}
-status_t Surface::unlockAndPost() {
- if (heapBase(0) == 0) return INVALID_OPERATION;
- if (heapBase(1) == 0) return INVALID_OPERATION;
- return mClient->unlockAndPostSurface(this);
+void Surface::_send_dirty_region(
+ layer_cblk_t* lcblk, const Region& dirty)
+{
+ const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
+ flat_region_t* flat_region = lcblk->region + index;
+ status_t err = dirty.write(flat_region, sizeof(flat_region_t));
+ if (err < NO_ERROR) {
+ // region doesn't fit, use the bounds
+ const Region reg(dirty.bounds());
+ reg.write(flat_region, sizeof(flat_region_t));
+ }
}
-status_t Surface::unlock() {
- if (heapBase(0) == 0) return INVALID_OPERATION;
- if (heapBase(1) == 0) return INVALID_OPERATION;
- return mClient->unlockSurface(this);
-}
status_t Surface::setLayer(int32_t layer) {
return mClient->setLayer(this, layer);
@@ -183,8 +521,6 @@
ISurfaceFlingerClient::surface_data_t data;
sp<IBinder> clientBinder= parcel->readStrongBinder();
sp<ISurface> surface = interface_cast<ISurface>(parcel->readStrongBinder());
- data.heap[0] = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
- data.heap[1] = interface_cast<IMemoryHeap>(parcel->readStrongBinder());
data.token = parcel->readInt32();
data.identity = parcel->readInt32();
PixelFormat format = parcel->readInt32();
@@ -204,21 +540,16 @@
uint32_t identity = 0;
sp<SurfaceComposerClient> client;
sp<ISurface> sur;
- sp<IMemoryHeap> heap[2];
if (surface->isValid()) {
token = surface->mToken;
identity = surface->mIdentity;
client = surface->mClient;
sur = surface->mSurface;
- heap[0] = surface->mHeap[0];
- heap[1] = surface->mHeap[1];
format = surface->mFormat;
flags = surface->mFlags;
}
parcel->writeStrongBinder(client!=0 ? client->connection() : NULL);
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
- parcel->writeStrongBinder(heap[0]!=0 ? heap[0]->asBinder() : NULL);
- parcel->writeStrongBinder(heap[1]!=0 ? heap[1]->asBinder() : NULL);
parcel->writeInt32(token);
parcel->writeInt32(identity);
parcel->writeInt32(format);
@@ -233,23 +564,24 @@
return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
}
-void* Surface::heapBase(int i) const
+status_t Surface::getBufferLocked(int index)
{
- void* heapBase = mSurfaceHeapBase[i];
- // map lazily so it doesn't get mapped in clients that don't need it
- if (heapBase == 0) {
- const sp<IMemoryHeap>& heap(mHeap[i]);
- if (heap != 0) {
- heapBase = static_cast<uint8_t*>(heap->base());
- if (heapBase == MAP_FAILED) {
- heapBase = NULL;
- LOGE("Couldn't map Surface's heap (binder=%p, heap=%p)",
- heap->asBinder().get(), heap.get());
- }
- mSurfaceHeapBase[i] = heapBase;
+ status_t err = NO_MEMORY;
+ sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+ LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
+ if (buffer != 0) {
+ sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
+ if (currentBuffer != 0) {
+ BufferMapper::get().unmap(currentBuffer->getHandle());
+ currentBuffer.clear();
+ }
+ err = BufferMapper::get().map(buffer->getHandle(), &buffer->bits);
+ LOGW_IF(err, "map(...) failed %d (%s)", err, strerror(-err));
+ if (err == NO_ERROR) {
+ currentBuffer = buffer;
}
}
- return heapBase;
+ return err;
}
}; // namespace android
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/ui/SurfaceComposerClient.cpp
index fe803ff..e1b13c7 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/ui/SurfaceComposerClient.cpp
@@ -29,27 +29,21 @@
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>
-#include <utils/IPCThreadState.h>
#include <utils/IServiceManager.h>
#include <utils/IMemory.h>
#include <utils/Log.h>
+#include <ui/DisplayInfo.h>
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
#include <ui/ISurface.h>
#include <ui/SurfaceComposerClient.h>
-#include <ui/DisplayInfo.h>
#include <ui/Rect.h>
-#include <ui/Point.h>
#include <private/ui/SharedState.h>
#include <private/ui/LayerState.h>
#include <private/ui/SurfaceFlingerSynchro.h>
-#include <pixelflinger/pixelflinger.h>
-
-#include <utils/BpBinder.h>
-
#define VERBOSE(...) ((void)0)
//#define VERBOSE LOGD
@@ -109,50 +103,8 @@
// ---------------------------------------------------------------------------
-static void copyBlt(const GGLSurface& dst,
- const GGLSurface& src, const Region& reg)
-{
- Region::iterator iterator(reg);
- if (iterator) {
- // NOTE: dst and src must be the same format
- Rect r;
- 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 = src.data + (r.left + src.stride * r.top) * bpp;
- uint8_t* d = dst.data + (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);
- }
- }
- }
-}
-
-// ---------------------------------------------------------------------------
-
-surface_flinger_cblk_t::surface_flinger_cblk_t()
-{
-}
-
-// ---------------------------------------------------------------------------
-
-per_client_cblk_t::per_client_cblk_t()
-{
-}
-
// these functions are used by the clients
-inline status_t per_client_cblk_t::validate(size_t i) const {
+status_t per_client_cblk_t::validate(size_t i) const {
if (uint32_t(i) >= NUM_LAYERS_MAX)
return BAD_INDEX;
if (layers[i].swapState & eInvalidSurface)
@@ -248,8 +200,9 @@
index = (state&eIndex) ^ ((state&eFlipRequested)>>1);
// make sure this buffer is valid
- if (layer->surface[index].bits_offset < 0) {
- return status_t(layer->surface[index].bits_offset);
+ status_t err = layer->surface[index].status;
+ if (err < 0) {
+ return err;
}
if (inspect) {
@@ -273,7 +226,7 @@
uint32_t per_client_cblk_t::unlock_layer_and_post(size_t i)
{
- // atomically set eFlipRequested and clear eLocked and optionnaly
+ // atomically set eFlipRequested and clear eLocked and optionally
// set eNextFlipPending if eFlipRequested was already set
layer_cblk_t * const layer = layers + i;
@@ -290,7 +243,7 @@
if (oldvalue & eFlipRequested)
newvalue |= eNextFlipPending;
- // if eFlipRequested was alread set, set eNextFlipPending
+ // if eFlipRequested was already set, set eNextFlipPending
} while (android_atomic_cmpxchg(oldvalue, newvalue, &(layer->swapState)));
@@ -298,9 +251,9 @@
int(i), int((layer->flags & eBufferIndex) >> eBufferIndexShift),
int(newvalue));
- // from this point, the server can kick in at anytime and use the first
+ // from this point, the server can kick in at any time and use the first
// buffer, so we cannot use it anymore, and we must use the 'other'
- // buffer instead (or wait if it is not availlable yet, see lock_layer).
+ // buffer instead (or wait if it is not available yet, see lock_layer).
return newvalue;
}
@@ -376,32 +329,6 @@
return mStatus;
}
-status_t SurfaceComposerClient::validateSurface(
- per_client_cblk_t const* cblk, Surface const * surface)
-{
- SurfaceID index = surface->ID();
- if (cblk == 0) {
- LOGE("cblk is null (surface id=%d, identity=%u)",
- index, surface->getIdentity());
- return NO_INIT;
- }
-
- status_t err = cblk->validate(index);
- if (err != NO_ERROR) {
- LOGE("surface (id=%d, identity=%u) is invalid, err=%d (%s)",
- index, surface->getIdentity(), err, strerror(-err));
- return err;
- }
-
- if (surface->getIdentity() != uint32_t(cblk->layers[index].identity)) {
- LOGE("using an invalid surface id=%d, identity=%u should be %d",
- index, surface->getIdentity(), cblk->layers[index].identity);
- return NO_INIT;
- }
-
- return NO_ERROR;
-}
-
sp<IBinder> SurfaceComposerClient::connection() const
{
return (mClient != 0) ? mClient->asBinder() : 0;
@@ -439,7 +366,6 @@
sp<IMemory> controlMemory;
sp<ISurfaceFlingerClient> client;
- sp<IMemoryHeap> surfaceHeap;
{
Mutex::Autolock _lg(gLock);
@@ -462,9 +388,7 @@
delete mPrebuiltLayerState;
mPrebuiltLayerState = 0;
controlMemory = mControlMemory;
- surfaceHeap = mSurfaceHeap;
mControlMemory.clear();
- mSurfaceHeap.clear();
mControl = 0;
mStatus = NO_INIT;
}
@@ -528,6 +452,12 @@
return n;
}
+
+void SurfaceComposerClient::signalServer()
+{
+ mSignalServer->signal();
+}
+
sp<Surface> SurfaceComposerClient::createSurface(
int pid,
DisplayID display,
@@ -568,186 +498,6 @@
return err;
}
-status_t SurfaceComposerClient::nextBuffer(Surface* surface,
- Surface::SurfaceInfo* info)
-{
- SurfaceID index = surface->ID();
- per_client_cblk_t* const cblk = mControl;
- status_t err = validateSurface(cblk, surface);
- if (err != NO_ERROR)
- return err;
-
- int32_t backIdx = surface->mBackbufferIndex;
- layer_cblk_t* const lcblk = &(cblk->layers[index]);
- const surface_info_t* const front = lcblk->surface + (1-backIdx);
- info->w = front->w;
- info->h = front->h;
- info->format = front->format;
- info->base = surface->heapBase(1-backIdx);
- info->bits = reinterpret_cast<void*>(intptr_t(info->base) + front->bits_offset);
- info->bpr = front->bpr;
-
- return 0;
-}
-
-status_t SurfaceComposerClient::lockSurface(
- Surface* surface,
- Surface::SurfaceInfo* other,
- Region* dirty,
- bool blocking)
-{
- Mutex::Autolock _l(surface->getLock());
-
- SurfaceID index = surface->ID();
- per_client_cblk_t* const cblk = mControl;
- status_t err = validateSurface(cblk, surface);
- if (err != NO_ERROR)
- return err;
-
- int32_t backIdx = cblk->lock_layer(size_t(index),
- per_client_cblk_t::BLOCKING);
- if (backIdx >= 0) {
- surface->mBackbufferIndex = backIdx;
- layer_cblk_t* const lcblk = &(cblk->layers[index]);
- const surface_info_t* const back = lcblk->surface + backIdx;
- const surface_info_t* const front = lcblk->surface + (1-backIdx);
- other->w = back->w;
- other->h = back->h;
- other->format = back->format;
- other->base = surface->heapBase(backIdx);
- other->bits = reinterpret_cast<void*>(intptr_t(other->base) + back->bits_offset);
- other->bpr = back->bpr;
-
- const Rect bounds(other->w, other->h);
- Region newDirtyRegion;
-
- if (back->flags & surface_info_t::eBufferDirty) {
- /* it is safe to write *back here, because we're guaranteed
- * SurfaceFlinger is not touching it (since it just granted
- * access to us) */
- const_cast<surface_info_t*>(back)->flags &=
- ~surface_info_t::eBufferDirty;
-
- // content is meaningless in this case and the whole surface
- // needs to be redrawn.
-
- newDirtyRegion.set(bounds);
- if (dirty) {
- *dirty = newDirtyRegion;
- }
-
- //if (bytesPerPixel(other->format) == 4) {
- // android_memset32(
- // (uint32_t*)other->bits, 0xFF00FF00, other->h * other->bpr);
- //} else {
- // android_memset16( // fill with green
- // (uint16_t*)other->bits, 0x7E0, other->h * other->bpr);
- //}
- }
- else
- {
- if (dirty) {
- dirty->andSelf(Region(bounds));
- newDirtyRegion = *dirty;
- } else {
- newDirtyRegion.set(bounds);
- }
-
- Region copyback;
- if (!(lcblk->flags & eNoCopyBack)) {
- const Region previousDirtyRegion(surface->dirtyRegion());
- copyback = previousDirtyRegion.subtract(newDirtyRegion);
- }
-
- if (!copyback.isEmpty()) {
- // copy front to back
- GGLSurface cb;
- cb.version = sizeof(GGLSurface);
- cb.width = back->w;
- cb.height = back->h;
- cb.stride = back->stride;
- cb.data = (GGLubyte*)surface->heapBase(backIdx);
- cb.data += back->bits_offset;
- cb.format = back->format;
-
- GGLSurface t;
- t.version = sizeof(GGLSurface);
- t.width = front->w;
- t.height = front->h;
- t.stride = front->stride;
- t.data = (GGLubyte*)surface->heapBase(1-backIdx);
- t.data += front->bits_offset;
- t.format = front->format;
-
- //const Region copyback(lcblk->region + 1-backIdx);
- copyBlt(cb, t, copyback);
- }
- }
-
- // update dirty region
- surface->setDirtyRegion(newDirtyRegion);
- }
- return (backIdx < 0) ? status_t(backIdx) : status_t(NO_ERROR);
-}
-
-void SurfaceComposerClient::_signal_server()
-{
- mSignalServer->signal();
-}
-
-void SurfaceComposerClient::_send_dirty_region(
- layer_cblk_t* lcblk, const Region& dirty)
-{
- const int32_t index = (lcblk->flags & eBufferIndex) >> eBufferIndexShift;
- flat_region_t* flat_region = lcblk->region + index;
- status_t err = dirty.write(flat_region, sizeof(flat_region_t));
- if (err < NO_ERROR) {
- // region doesn't fit, use the bounds
- const Region reg(dirty.bounds());
- reg.write(flat_region, sizeof(flat_region_t));
- }
-}
-
-status_t SurfaceComposerClient::unlockAndPostSurface(Surface* surface)
-{
- Mutex::Autolock _l(surface->getLock());
-
- SurfaceID index = surface->ID();
- per_client_cblk_t* const cblk = mControl;
- status_t err = validateSurface(cblk, surface);
- if (err != NO_ERROR)
- return err;
-
- Region dirty(surface->dirtyRegion());
- const Rect& swapRect(surface->swapRectangle());
- if (swapRect.isValid()) {
- dirty.set(swapRect);
- }
-
- // transmit the dirty region
- layer_cblk_t* const lcblk = &(cblk->layers[index]);
- _send_dirty_region(lcblk, dirty);
- uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
- if (!(newstate & eNextFlipPending))
- _signal_server();
- return NO_ERROR;
-}
-
-status_t SurfaceComposerClient::unlockSurface(Surface* surface)
-{
- Mutex::Autolock _l(surface->getLock());
-
- SurfaceID index = surface->ID();
- per_client_cblk_t* const cblk = mControl;
- status_t err = validateSurface(cblk, surface);
- if (err != NO_ERROR)
- return err;
-
- layer_cblk_t* const lcblk = &(cblk->layers[index]);
- cblk->unlock_layer(size_t(index));
- return NO_ERROR;
-}
-
void SurfaceComposerClient::openGlobalTransaction()
{
Mutex::Autolock _l(gLock);
@@ -870,7 +620,7 @@
{
SurfaceID index = surface->ID();
per_client_cblk_t* const cblk = mControl;
- status_t err = validateSurface(cblk, surface.get());
+ status_t err = surface->validate(cblk);
if (err != NO_ERROR)
return 0;
@@ -973,7 +723,6 @@
return NO_ERROR;
}
-
status_t SurfaceComposerClient::setTransparentRegionHint(
Surface* surface, const Region& transparentRegion)
{