diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h index e72357a60190d..cb9bf940e23ae 100644 --- a/include/ui/FramebufferNativeWindow.h +++ b/include/ui/FramebufferNativeWindow.h @@ -62,6 +62,7 @@ private: 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 int query(android_native_window_t* window, int what, int* value); framebuffer_device_t* fbDev; alloc_device_t* grDev; diff --git a/include/ui/Surface.h b/include/ui/Surface.h index 8c4f63ddfec09..156d453b2d20c 100644 --- a/include/ui/Surface.h +++ b/include/ui/Surface.h @@ -115,6 +115,8 @@ private: sp mSurface; SurfaceID mToken; uint32_t mIdentity; + uint32_t mWidth; + uint32_t mHeight; PixelFormat mFormat; uint32_t mFlags; mutable Mutex mLock; @@ -192,10 +194,12 @@ private: 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 int query(android_native_window_t* window, int what, int* value); int dequeueBuffer(android_native_buffer_t** buffer); int lockBuffer(android_native_buffer_t* buffer); int queueBuffer(android_native_buffer_t* buffer); + int query(int what, int* value); status_t dequeueBuffer(sp* buffer); status_t lockBuffer(const sp& buffer); @@ -209,6 +213,8 @@ private: sp mLockedBuffer; SurfaceID mToken; uint32_t mIdentity; + uint32_t mWidth; + uint32_t mHeight; PixelFormat mFormat; uint32_t mFlags; mutable Region mDirtyRegion; diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index 0398ea7eb7c17..a3a1316fa5043 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -60,6 +60,12 @@ struct android_native_base_t // --------------------------------------------------------------------------- +/* attributes queriable with query() */ +enum { + NATIVE_WINDOW_WIDTH = 0, + NATIVE_WINDOW_HEIGHT = 1 +}; + struct android_native_window_t { #ifdef __cplusplus @@ -129,8 +135,15 @@ struct android_native_window_t int (*queueBuffer)(struct android_native_window_t* window, struct android_native_buffer_t* buffer); + /* + * hook used to retrieve information about the native window. + * + * Returns 0 on success or -errno on error. + */ + int (*query)(struct android_native_window_t* window, + int what, int* value); - void* reserved_proc[5]; + void* reserved_proc[4]; }; // --------------------------------------------------------------------------- diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp index 8c8fd6bb0f9dd..8b7ea21d73226 100644 --- a/libs/ui/FramebufferNativeWindow.cpp +++ b/libs/ui/FramebufferNativeWindow.cpp @@ -124,6 +124,7 @@ FramebufferNativeWindow::FramebufferNativeWindow() android_native_window_t::dequeueBuffer = dequeueBuffer; android_native_window_t::lockBuffer = lockBuffer; android_native_window_t::queueBuffer = queueBuffer; + android_native_window_t::query = query; } FramebufferNativeWindow::~FramebufferNativeWindow() { @@ -198,6 +199,23 @@ int FramebufferNativeWindow::queueBuffer(android_native_window_t* window, return res; } +int FramebufferNativeWindow::query(android_native_window_t* window, + int what, int* value) +{ + FramebufferNativeWindow* self = getSelf(window); + Mutex::Autolock _l(self->mutex); + framebuffer_device_t* fb = self->fbDev; + switch (what) { + case NATIVE_WINDOW_WIDTH: + *value = fb->width; + return NO_ERROR; + case NATIVE_WINDOW_HEIGHT: + *value = fb->height; + return NO_ERROR; + } + return BAD_VALUE; +} + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp index aef47fdad0657..04ab64c4abc6f 100644 --- a/libs/ui/Surface.cpp +++ b/libs/ui/Surface.cpp @@ -180,7 +180,7 @@ SurfaceControl::SurfaceControl( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) : mClient(client), mSurface(surface), mToken(data.token), mIdentity(data.identity), - mFormat(format), mFlags(flags) + mWidth(w), mHeight(h), mFormat(format), mFlags(flags) { } @@ -338,6 +338,8 @@ status_t SurfaceControl::writeSurfaceToParcel( uint32_t format = 0; SurfaceID token = -1; uint32_t identity = 0; + uint32_t width = 0; + uint32_t height = 0; sp client; sp sur; if (SurfaceControl::isValid(control)) { @@ -345,6 +347,8 @@ status_t SurfaceControl::writeSurfaceToParcel( identity = control->mIdentity; client = control->mClient; sur = control->mSurface; + width = control->mWidth; + height = control->mHeight; format = control->mFormat; flags = control->mFlags; } @@ -352,6 +356,8 @@ status_t SurfaceControl::writeSurfaceToParcel( parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); parcel->writeInt32(token); parcel->writeInt32(identity); + parcel->writeInt32(width); + parcel->writeInt32(height); parcel->writeInt32(format); parcel->writeInt32(flags); return NO_ERROR; @@ -373,6 +379,7 @@ sp SurfaceControl::getSurface() const Surface::Surface(const sp& surface) : mClient(surface->mClient), mSurface(surface->mSurface), mToken(surface->mToken), mIdentity(surface->mIdentity), + mWidth(surface->mWidth), mHeight(surface->mHeight), mFormat(surface->mFormat), mFlags(surface->mFlags), mBufferMapper(BufferMapper::get()) { @@ -386,6 +393,8 @@ Surface::Surface(const Parcel& parcel) mSurface = interface_cast(parcel.readStrongBinder()); mToken = parcel.readInt32(); mIdentity = parcel.readInt32(); + mWidth = parcel.readInt32(); + mHeight = parcel.readInt32(); mFormat = parcel.readInt32(); mFlags = parcel.readInt32(); @@ -401,6 +410,7 @@ void Surface::init() android_native_window_t::dequeueBuffer = dequeueBuffer; android_native_window_t::lockBuffer = lockBuffer; android_native_window_t::queueBuffer = queueBuffer; + android_native_window_t::query = query; mSwapRectangle.makeInvalid(); DisplayInfo dinfo; SurfaceComposerClient::getDisplayInfo(0, &dinfo); @@ -492,6 +502,13 @@ int Surface::queueBuffer(android_native_window_t* window, return self->queueBuffer(buffer); } +int Surface::query(android_native_window_t* window, + int what, int* value) +{ + Surface* self = getSelf(window); + return self->query(what, value); +} + // ---------------------------------------------------------------------------- status_t Surface::dequeueBuffer(sp* buffer) @@ -499,6 +516,9 @@ status_t Surface::dequeueBuffer(sp* buffer) android_native_buffer_t* out; status_t err = dequeueBuffer(&out); *buffer = SurfaceBuffer::getSelf(out); + // reset the width/height with the what we get from the buffer + mWidth = uint32_t(out->width); + mHeight = uint32_t(out->height); return err; } @@ -586,6 +606,19 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) return NO_ERROR; } +int Surface::query(int what, int* value) +{ + switch (what) { + case NATIVE_WINDOW_WIDTH: + *value = int(mWidth); + return NO_ERROR; + case NATIVE_WINDOW_HEIGHT: + *value = int(mHeight); + return NO_ERROR; + } + return BAD_VALUE; +} + // ---------------------------------------------------------------------------- status_t Surface::lock(SurfaceInfo* info, bool blocking) { diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 7afcae7504f89..b0e54d8f2730d 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -216,8 +216,8 @@ struct egl_window_surface_v2_t : public egl_surface_t virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual void connect(); virtual void disconnect(); - virtual EGLint getWidth() const { return buffer->width; } - virtual EGLint getHeight() const { return buffer->height; } + virtual EGLint getWidth() const { return width; } + virtual EGLint getHeight() const { return height; } virtual EGLint getHorizontalResolution() const; virtual EGLint getVerticalResolution() const; virtual EGLint getRefreshRate() const; @@ -365,26 +365,8 @@ egl_window_surface_v2_t::egl_window_surface_v2_t(EGLDisplay dpy, // keep a reference on the window nativeWindow->common.incRef(&nativeWindow->common); - - // dequeue a buffer - nativeWindow->dequeueBuffer(nativeWindow, &buffer); - - // allocate a corresponding depth-buffer - width = buffer->width; - height = buffer->height; - if (depthFormat) { - depth.width = width; - depth.height = height; - depth.stride = depth.width; // use the width here - depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); - if (depth.data == 0) { - setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); - return; - } - } - - // keep a reference on the buffer - buffer->common.incRef(&buffer->common); + nativeWindow->query(nativeWindow, NATIVE_WINDOW_WIDTH, &width); + nativeWindow->query(nativeWindow, NATIVE_WINDOW_HEIGHT, &height); } egl_window_surface_v2_t::~egl_window_surface_v2_t() { @@ -402,6 +384,26 @@ egl_window_surface_v2_t::~egl_window_surface_v2_t() { void egl_window_surface_v2_t::connect() { + // dequeue a buffer + nativeWindow->dequeueBuffer(nativeWindow, &buffer); + + // allocate a corresponding depth-buffer + width = buffer->width; + height = buffer->height; + if (depth.format) { + depth.width = width; + depth.height = height; + depth.stride = depth.width; // use the width here + depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2); + if (depth.data == 0) { + setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return; + } + } + + // keep a reference on the buffer + buffer->common.incRef(&buffer->common); + // Lock the buffer nativeWindow->lockBuffer(nativeWindow, buffer); // pin the buffer down @@ -420,6 +422,16 @@ void egl_window_surface_v2_t::disconnect() bits = NULL; unlock(buffer); } + // enqueue the last frame + nativeWindow->queueBuffer(nativeWindow, buffer); + if (buffer) { + buffer->common.decRef(&buffer->common); + buffer = 0; + } + if (previousBuffer) { + previousBuffer->common.decRef(&previousBuffer->common); + previousBuffer = 0; + } } status_t egl_window_surface_v2_t::lock(