Merge change I8d2de438 into eclair
* changes:
fix [2143798] Need to figure out how to do video
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 8897f03..2172536 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -66,7 +66,11 @@
GraphicBuffer();
// creates w * h buffer
- GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t ssage);
+ GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+
+ // create a buffer from an existing handle
+ GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t stride, native_handle_t* handle, bool keepOwnership);
// return status
status_t initCheck() const;
@@ -94,9 +98,15 @@
GraphicBuffer(const Parcel& reply);
virtual ~GraphicBuffer();
+ enum {
+ ownNone = 0,
+ ownHandle = 1,
+ ownData = 2,
+ };
+
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
- bool mOwner;
+ uint8_t mOwner;
private:
friend class Surface;
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 @@
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 @@
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 @@
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 @@
buffer->width, buffer->height, buffer->format,
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
- initializeEglImageLocked(
+ initializeEglImage(
mHybridBuffer, &mTextures[0]);
}
@@ -279,7 +224,9 @@
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 @@
}
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 @@
}
}
+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 @@
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 @@
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 @@
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 @@
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;
- }
+ if (UNLIKELY(mTexture.name == -1LU)) {
+ mTexture.name = mLayer.createTexture();
+ }
-#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;
+#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);
- /* 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();
- }
-
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-
- 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// ===========================================================================
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(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 @@
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()
{
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 @@
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);
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 2522656..9837845 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -25,6 +25,13 @@
primitives.cpp.arm \
vertex.cpp.arm
+LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
+LOCAL_LDLIBS := -lpthread -ldl
+
ifeq ($(TARGET_ARCH),arm)
LOCAL_SRC_FILES += fixed_asm.S iterators.S
LOCAL_CFLAGS += -fstrict-aliasing
@@ -38,15 +45,9 @@
ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1)
LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS
LOCAL_SRC_FILES += copybit.cpp
+ LOCAL_SHARED_LIBRARIES += libui
endif
-LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
LOCAL_MODULE:= libGLES_android
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
index 73b2355..0c3d0ee 100644
--- a/opengl/libagl/copybit.cpp
+++ b/opengl/libagl/copybit.cpp
@@ -33,6 +33,10 @@
#include <hardware/copybit.h>
#include <private/ui/android_natives_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
+#include <ui/Rect.h>
+
#define DEBUG_COPYBIT true
@@ -175,16 +179,6 @@
dtdy /= screen_h;
}
dtdy = -dtdy; // see equation of dtdy above
- if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
- || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
- // The requested scale is out of the range the hardware
- // can support.
- LOGD_IF(DEBUG_COPYBIT,
- "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
- "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
- dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
- return false;
- }
// copybit doesn't say anything about filtering, so we can't
// discriminate. On msm7k, copybit will always filter.
@@ -278,21 +272,93 @@
return false;
}
-
- // LOGW("calling copybits");
-
copybit_device_t* copybit = c->copybits.blitEngine;
+ copybit_image_t src;
+ buffer_handle_t source_hnd = textureObject->buffer->handle;
+ textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src);
+ copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
+
+ /*
+ * Below we perform extra passes needed to emulate things the h/w
+ * cannot do.
+ */
+
+ const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16);
+ const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16);
+
+ sp<GraphicBuffer> tempBitmap;
+
+ if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+ dtdy < maxScaleInv || dtdy > minScaleInv)
+ {
+ // The requested scale is out of the range the hardware
+ // can support.
+ LOGD_IF(DEBUG_COPYBIT,
+ "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+ "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+ dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+
+ int32_t xscale=0x10000, yscale=0x10000;
+ if (dsdx > minScaleInv) xscale = c->copybits.minScale;
+ else if (dsdx < maxScaleInv) xscale = c->copybits.maxScale;
+ if (dtdy > minScaleInv) yscale = c->copybits.minScale;
+ else if (dtdy < maxScaleInv) yscale = c->copybits.maxScale;
+ dsdx = gglMulx(dsdx, xscale);
+ dtdy = gglMulx(dtdy, yscale);
+
+ /* we handle only one step of resizing below. Handling an arbitrary
+ * number is relatively easy (replace "if" above by "while"), but requires
+ * two intermediate buffers and so far we never had the need.
+ */
+
+ if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+ dtdy < maxScaleInv || dtdy > minScaleInv) {
+ LOGD_IF(DEBUG_COPYBIT,
+ "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+ "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+ dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+ return false;
+ }
+
+ const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16);
+ const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16);
+
+ LOGD_IF(DEBUG_COPYBIT,
+ "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d",
+ xscale, yscale, dsdx, dtdy, tmp_w, tmp_h);
+
+ tempBitmap = new GraphicBuffer(
+ tmp_w, tmp_h, src.format,
+ GraphicBuffer::USAGE_HW_2D);
+
+ status_t err = tempBitmap->initCheck();
+ if (err == NO_ERROR) {
+ copybit_image_t tmp_dst;
+ copybit_rect_t tmp_rect;
+ tmp_dst.w = tmp_w;
+ tmp_dst.h = tmp_h;
+ tmp_dst.format = src.format;
+ tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
+ tmp_rect.l = 0;
+ tmp_rect.t = 0;
+ tmp_rect.r = tmp_dst.w;
+ tmp_rect.b = tmp_dst.h;
+ region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.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_dst, &src, &tmp_rect, &srect, &tmp_it);
+ src = tmp_dst;
+ srect = tmp_rect;
+ }
+ }
copybit_image_t dst;
buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer;
textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst);
copybit_rect_t drect = {x, y, x+w, y+h};
- copybit_image_t src;
- buffer_handle_t source_hnd = textureObject->buffer->handle;
- textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src);
- copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
-
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
copybit->set_parameter(copybit, COPYBIT_DITHER,