summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2009-10-26 20:12:37 -0700
committerMathias Agopian <mathias@google.com>2009-10-27 13:13:29 -0700
commit9042b4564de5477b18e680c7dce13b587a681dd9 (patch)
tree04872061371527ef76dbfff6ee0d6c8fdadb99bc /libs
parent678cdbe55e0de71436f8aad5f139eafc2ab6f937 (diff)
downloadframeworks_base-9042b4564de5477b18e680c7dce13b587a681dd9.zip
frameworks_base-9042b4564de5477b18e680c7dce13b587a681dd9.tar.gz
frameworks_base-9042b4564de5477b18e680c7dce13b587a681dd9.tar.bz2
fix [2143798] Need to figure out how to do video
Use EGLImageKHR instead of copybit directly. We now have the basis to use streaming YUV textures (well, in fact we already are). When/if we use the GPU instead of the MDP we'll need to make sure it supports the appropriate YUV format. Also make sure we compile if EGL_ANDROID_image_native_buffer is not supported
Diffstat (limited to 'libs')
-rw-r--r--libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp4
-rw-r--r--libs/surfaceflinger/Layer.cpp65
-rw-r--r--libs/surfaceflinger/Layer.h2
-rw-r--r--libs/surfaceflinger/LayerBase.cpp57
-rw-r--r--libs/surfaceflinger/LayerBase.h2
-rw-r--r--libs/surfaceflinger/LayerBuffer.cpp143
-rw-r--r--libs/surfaceflinger/LayerBuffer.h1
-rw-r--r--libs/surfaceflinger/LayerDim.cpp7
-rw-r--r--libs/ui/GraphicBuffer.cpp28
9 files changed, 117 insertions, 192 deletions
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f84933e..1abfd68 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -256,12 +256,16 @@ void DisplayHardware::init(uint32_t dpy)
if (strstr(gl_extensions, "GL_OES_draw_texture")) {
mFlags |= DRAW_TEXTURE_EXTENSION;
}
+#ifdef EGL_ANDROID_image_native_buffer
if (strstr( gl_extensions, "GL_OES_EGL_image") &&
(strstr(egl_extensions, "EGL_KHR_image_base") ||
strstr(egl_extensions, "EGL_KHR_image")) &&
strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
mFlags |= DIRECT_TEXTURE;
}
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
// Unbind the context from this thread
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 2bb1e12..f5a5a0b 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -130,62 +130,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
return NO_ERROR;
}
-status_t Layer::initializeEglImageLocked(
- const sp<GraphicBuffer>& buffer, Texture* texture)
-{
- status_t err = NO_ERROR;
-
- // we need to recreate the texture
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
-
- // free the previous image
- if (texture->image != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, texture->image);
- texture->image = EGL_NO_IMAGE_KHR;
- }
-
- // construct an EGL_NATIVE_BUFFER_ANDROID
- android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
-
- // create the new EGLImageKHR
- const EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE, EGL_NONE
- };
- texture->image = eglCreateImageKHR(
- dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- (EGLClientBuffer)clientBuf, attrs);
-
- LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
- "eglCreateImageKHR() failed. err=0x%4x",
- eglGetError());
-
- if (texture->image != EGL_NO_IMAGE_KHR) {
- glBindTexture(GL_TEXTURE_2D, texture->name);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
- (GLeglImageOES)texture->image);
- GLint error = glGetError();
- if (UNLIKELY(error != GL_NO_ERROR)) {
- // this failed, for instance, because we don't support NPOT.
- // FIXME: do something!
- LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
- "failed err=0x%04x",
- this, texture->image, error);
- mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
- err = INVALID_OPERATION;
- } else {
- // Everything went okay!
- texture->NPOTAdjust = false;
- texture->dirty = false;
- texture->width = clientBuf->width;
- texture->height = clientBuf->height;
- }
- } else {
- err = INVALID_OPERATION;
- }
- return err;
-}
-
void Layer::reloadTexture(const Region& dirty)
{
Mutex::Autolock _l(mLock);
@@ -199,10 +143,11 @@ void Layer::reloadTexture(const Region& dirty)
mTextures[index].height = 0;
}
+#ifdef EGL_ANDROID_image_native_buffer
if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
if (mTextures[index].dirty) {
- initializeEglImageLocked(buffer, &mTextures[index]);
+ initializeEglImage(buffer, &mTextures[index]);
}
} else {
if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
@@ -212,7 +157,7 @@ void Layer::reloadTexture(const Region& dirty)
buffer->width, buffer->height, buffer->format,
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
- initializeEglImageLocked(
+ initializeEglImage(
mHybridBuffer, &mTextures[0]);
}
@@ -279,7 +224,9 @@ void Layer::reloadTexture(const Region& dirty)
buffer->unlock();
}
}
- } else {
+ } else
+#endif
+ {
for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
mTextures[i].image = EGL_NO_IMAGE_KHR;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 57b3dfa..1310ecc 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -85,8 +85,6 @@ private:
}
void reloadTexture(const Region& dirty);
- status_t initializeEglImageLocked(
- const sp<GraphicBuffer>& buffer, Texture* texture);
uint32_t getEffectiveUsage(uint32_t usage) const;
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index ecc7894..8003d22 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -617,6 +617,63 @@ void LayerBase::loadTexture(Texture* texture,
}
}
+status_t LayerBase::initializeEglImage(
+ const sp<GraphicBuffer>& buffer, Texture* texture)
+{
+ status_t err = NO_ERROR;
+
+ // we need to recreate the texture
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+
+ // free the previous image
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(dpy, texture->image);
+ texture->image = EGL_NO_IMAGE_KHR;
+ }
+
+ // construct an EGL_NATIVE_BUFFER_ANDROID
+ android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+ // create the new EGLImageKHR
+ const EGLint attrs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE, EGL_NONE
+ };
+ texture->image = eglCreateImageKHR(
+ dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)clientBuf, attrs);
+
+ LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
+ "eglCreateImageKHR() failed. err=0x%4x",
+ eglGetError());
+
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ glBindTexture(GL_TEXTURE_2D, texture->name);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+ (GLeglImageOES)texture->image);
+ GLint error = glGetError();
+ if (UNLIKELY(error != GL_NO_ERROR)) {
+ // this failed, for instance, because we don't support NPOT.
+ // FIXME: do something!
+ LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
+ "failed err=0x%04x",
+ this, texture->image, error);
+ mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+ err = INVALID_OPERATION;
+ } else {
+ // Everything went okay!
+ texture->NPOTAdjust = false;
+ texture->dirty = false;
+ texture->width = clientBuf->width;
+ texture->height = clientBuf->height;
+ }
+ } else {
+ err = INVALID_OPERATION;
+ }
+ return err;
+}
+
+
// ---------------------------------------------------------------------------
int32_t LayerBaseClient::sIdentity = 0;
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index efa4f8c..ed07b3f 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -261,6 +261,8 @@ protected:
void drawWithOpenGL(const Region& clip, const Texture& texture) const;
void loadTexture(Texture* texture,
const Region& dirty, const GGLSurface& t) const;
+ status_t initializeEglImage(
+ const sp<GraphicBuffer>& buffer, Texture* texture);
sp<SurfaceFlinger> mFlinger;
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 7e27a02..6590503 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -339,12 +339,6 @@ LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
mLayer.forceVisibilityTransaction();
-
- hw_module_t const* module;
- mBlitEngine = NULL;
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
- copybit_open(module, &mBlitEngine);
- }
}
LayerBuffer::BufferSource::~BufferSource()
@@ -352,8 +346,9 @@ LayerBuffer::BufferSource::~BufferSource()
if (mTexture.name != -1U) {
glDeleteTextures(1, &mTexture.name);
}
- if (mBlitEngine) {
- copybit_close(mBlitEngine);
+ if (mTexture.image != EGL_NO_IMAGE_KHR) {
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+ eglDestroyImageKHR(dpy, mTexture.image);
}
}
@@ -421,122 +416,28 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
status_t err = NO_ERROR;
NativeBuffer src(ourBuffer->getBuffer());
const Rect transformedBounds(mLayer.getTransformedBounds());
- copybit_device_t* copybit = mBlitEngine;
-
- if (copybit) {
- const int src_width = src.crop.r - src.crop.l;
- const int src_height = src.crop.b - src.crop.t;
- int W = transformedBounds.width();
- int H = transformedBounds.height();
- if (mLayer.getOrientation() & Transform::ROT_90) {
- int t(W); W=H; H=t;
- }
-
-#ifdef EGL_ANDROID_get_render_buffer
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
- EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
- android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
- if (nb == 0) {
- err = BAD_VALUE;
- } else {
- copybit_image_t dst;
- dst.w = nb->width;
- dst.h = nb->height;
- dst.format = nb->format;
- dst.base = NULL; // unused by copybit on msm7k
- dst.handle = (native_handle_t *)nb->handle;
-
- /* With LayerBuffer, it is likely that we'll have to rescale the
- * surface, because this is often used for video playback or
- * camera-preview. Since we want these operation as fast as possible
- * we make sure we can use the 2D H/W even if it doesn't support
- * the requested scale factor, in which case we perform the scaling
- * in several passes. */
-
- const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
- const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
-
- float xscale = 1.0f;
- if (src_width > W*min) xscale = 1.0f / min;
- else if (src_width*mag < W) xscale = mag;
-
- float yscale = 1.0f;
- if (src_height > H*min) yscale = 1.0f / min;
- else if (src_height*mag < H) yscale = mag;
-
- if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
- const int tmp_w = floorf(src_width * xscale);
- const int tmp_h = floorf(src_height * yscale);
-
- if (mTempBitmap==0 ||
- mTempBitmap->getWidth() < size_t(tmp_w) ||
- mTempBitmap->getHeight() < size_t(tmp_h)) {
- mTempBitmap.clear();
- mTempBitmap = new GraphicBuffer(
- tmp_w, tmp_h, src.img.format,
- GraphicBuffer::USAGE_HW_2D);
- err = mTempBitmap->initCheck();
- }
-
- if (LIKELY(err == NO_ERROR)) {
- NativeBuffer tmp;
- tmp.img.w = tmp_w;
- tmp.img.h = tmp_h;
- tmp.img.format = src.img.format;
- tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
- tmp.crop.l = 0;
- tmp.crop.t = 0;
- tmp.crop.r = tmp.img.w;
- tmp.crop.b = tmp.img.h;
-
- region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
- err = copybit->stretch(copybit,
- &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
- src = tmp;
- }
- }
- const Rect transformedBounds(mLayer.getTransformedBounds());
- const copybit_rect_t& drect =
- reinterpret_cast<const copybit_rect_t&>(transformedBounds);
- const State& s(mLayer.drawingState());
- region_iterator it(clip);
-
- // pick the right orientation for this buffer
- int orientation = mLayer.getOrientation();
- if (UNLIKELY(mBufferHeap.transform)) {
- Transform rot90;
- GraphicPlane::orientationToTransfrom(
- ISurfaceComposer::eOrientation90, 0, 0, &rot90);
- const Transform& planeTransform(mLayer.graphicPlane(0).transform());
- const Layer::State& s(mLayer.drawingState());
- Transform tr(planeTransform * s.transform * rot90);
- orientation = tr.getOrientation();
- }
+ if (UNLIKELY(mTexture.name == -1LU)) {
+ mTexture.name = mLayer.createTexture();
+ }
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+#if defined(EGL_ANDROID_image_native_buffer)
+ if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+ // NOTE: Assume the buffer is allocated with the proper USAGE flags
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
+ src.crop.r, src.crop.b, src.img.format,
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ src.img.w, src.img.handle, false);
- err = copybit->stretch(copybit,
- &dst, &src.img, &drect, &src.crop, &it);
- if (err != NO_ERROR) {
- LOGE("copybit failed (%s)", strerror(err));
- }
- }
+ err = mLayer.initializeEglImage(graphicBuffer, &mTexture);
}
#endif
-
- if (!copybit || err)
- {
+ else {
+ err = INVALID_OPERATION;
+ }
+
+ if (err != NO_ERROR) {
// OpenGL fall-back
- if (UNLIKELY(mTexture.name == -1LU)) {
- mTexture.name = mLayer.createTexture();
- }
GLuint w = 0;
GLuint h = 0;
GGLSurface t;
@@ -549,11 +450,11 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
t.data = (GGLubyte*)src.img.base;
const Region dirty(Rect(t.width, t.height));
mLayer.loadTexture(&mTexture, dirty, t);
- mTexture.transform = mBufferHeap.transform;
- mLayer.drawWithOpenGL(clip, mTexture);
}
-}
+ mTexture.transform = mBufferHeap.transform;
+ mLayer.drawWithOpenGL(clip, mTexture);
+}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 5eb472c..438b711 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -132,7 +132,6 @@ private:
size_t mBufferSize;
mutable sp<GraphicBuffer> mTempBitmap;
mutable LayerBase::Texture mTexture;
- copybit_device_t* mBlitEngine;
};
class OverlaySource : public Source {
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 538dc77..fd61e30 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -55,8 +55,8 @@ void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
sHeight = h;
sUseTexture = false;
-#ifdef DIM_WITH_TEXTURE
-
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+
#warning "using a texture to implement LayerDim"
/* On some h/w like msm7K, it is faster to use a texture because the
@@ -69,7 +69,6 @@ void LayerDim::initDimmer(SurfaceFlinger* flinger, uint32_t w, uint32_t h)
uint32_t flags = hw.getFlags();
if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
- // TODO: api to pass the usage flags
sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
@@ -123,7 +122,7 @@ void LayerDim::onDraw(const Region& clip) const
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4x(0, 0, 0, alpha);
-#ifdef DIM_WITH_TEXTURE
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
if (sUseTexture) {
glBindTexture(GL_TEXTURE_2D, sTexId);
glEnable(GL_TEXTURE_2D);
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 1cf20d7..efe2d78 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -37,7 +37,7 @@ namespace android {
// ===========================================================================
GraphicBuffer::GraphicBuffer()
- : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()),
+ : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
width =
@@ -50,7 +50,7 @@ GraphicBuffer::GraphicBuffer()
GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
PixelFormat reqFormat, uint32_t reqUsage)
- : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()),
+ : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
width =
@@ -62,8 +62,23 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
mInitCheck = initSize(w, h, reqFormat, reqUsage);
}
+GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat inFormat, uint32_t inUsage,
+ uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
+ : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
+ mBufferMapper(GraphicBufferMapper::get()),
+ mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
+{
+ width = w;
+ height = h;
+ stride = inStride;
+ format = inFormat;
+ usage = inUsage;
+ handle = inHandle;
+}
+
GraphicBuffer::GraphicBuffer(const Parcel& data)
- : BASE(), mOwner(true), mBufferMapper(GraphicBufferMapper::get()),
+ : BASE(), mOwner(ownHandle), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
// we own the handle in this case
@@ -83,10 +98,10 @@ GraphicBuffer::GraphicBuffer(const Parcel& data)
GraphicBuffer::~GraphicBuffer()
{
if (handle) {
- if (mOwner) {
+ if (mOwner == ownHandle) {
native_handle_close(handle);
native_handle_delete(const_cast<native_handle*>(handle));
- } else {
+ } else if (mOwner == ownData) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
}
@@ -106,6 +121,9 @@ android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
uint32_t reqUsage)
{
+ if (mOwner != ownData)
+ return INVALID_OPERATION;
+
if (handle) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);