fixed some issues with the software renderer when surfaces are made current.
there was several issues: - when a surface was made non-current, the last frame wasn't shown and the buffer could stay locked - when a surface was made current the 2nd time, it would not dequeue a new buffer now, queue/dequeue are done when the surface is made current. for this to work, a new query() hook had to be added on android_native_window_t, it allows to retrieve some attributes of a window (currently only width and height).
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -115,6 +115,8 @@ private:
|
||||
sp<ISurface> 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<SurfaceBuffer>* buffer);
|
||||
status_t lockBuffer(const sp<SurfaceBuffer>& buffer);
|
||||
@@ -209,6 +213,8 @@ private:
|
||||
sp<SurfaceBuffer> mLockedBuffer;
|
||||
SurfaceID mToken;
|
||||
uint32_t mIdentity;
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
PixelFormat mFormat;
|
||||
uint32_t mFlags;
|
||||
mutable Region mDirtyRegion;
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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<SurfaceComposerClient> client;
|
||||
sp<ISurface> 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<Surface> SurfaceControl::getSurface() const
|
||||
Surface::Surface(const sp<SurfaceControl>& 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<ISurface>(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<SurfaceBuffer>* buffer)
|
||||
@@ -499,6 +516,9 @@ status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* 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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user