summaryrefslogtreecommitdiff
path: root/libs/gui/GLConsumer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/gui/GLConsumer.cpp')
-rw-r--r--libs/gui/GLConsumer.cpp307
1 files changed, 95 insertions, 212 deletions
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 59e78cc6bf..885efec9b9 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -31,6 +31,8 @@
#include <hardware/hardware.h>
+#include <math/mat4.h>
+
#include <gui/BufferItem.h>
#include <gui/GLConsumer.h>
#include <gui/ISurfaceComposer.h>
@@ -75,33 +77,7 @@ static const struct {
"_______________"
};
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
+static const mat4 mtxIdentity;
Mutex GLConsumer::sStaticInitLock;
sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
@@ -173,7 +149,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
{
GLC_LOGV("GLConsumer");
- memcpy(mCurrentTransformMatrix, mtxIdentity,
+ memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
@@ -202,7 +178,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
{
GLC_LOGV("GLConsumer");
- memcpy(mCurrentTransformMatrix, mtxIdentity,
+ memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
@@ -315,7 +291,7 @@ status_t GLConsumer::releaseTexImage() {
return err;
}
- if (mReleasedTexImage == nullptr) {
+ if (mReleasedTexImage == NULL) {
mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
}
@@ -345,7 +321,7 @@ status_t GLConsumer::releaseTexImage() {
sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
Mutex::Autolock _l(sStaticInitLock);
- if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
+ if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
// The first time, create the debug texture in case the application
// continues to use it.
sp<GraphicBuffer> buffer = new GraphicBuffer(
@@ -381,7 +357,7 @@ status_t GLConsumer::acquireBufferLocked(BufferItem *item,
// If item->mGraphicBuffer is not null, this buffer has not been acquired
// before, so any prior EglImage created is using a stale buffer. This
// replaces any old EglImage with a new one (using the new buffer).
- if (item->mGraphicBuffer != nullptr) {
+ if (item->mGraphicBuffer != NULL) {
int slot = item->mSlot;
mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
}
@@ -455,7 +431,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
mCurrentTexture, mCurrentTextureImage != NULL ?
- mCurrentTextureImage->graphicBufferHandle() : nullptr,
+ mCurrentTextureImage->graphicBufferHandle() : 0,
slot, mSlots[slot].mGraphicBuffer->handle);
// Hang onto the pointer so that it isn't freed in the call to
@@ -515,7 +491,7 @@ status_t GLConsumer::bindTextureImageLocked() {
glBindTexture(mTexTarget, mTexName);
if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
- mCurrentTextureImage == nullptr) {
+ mCurrentTextureImage == NULL) {
GLC_LOGE("bindTextureImage: no currently-bound texture");
return NO_INIT;
}
@@ -679,7 +655,7 @@ status_t GLConsumer::attachToContext(uint32_t tex) {
mTexName = tex;
mAttached = true;
- if (mCurrentTextureImage != nullptr) {
+ if (mCurrentTextureImage != NULL) {
// This may wait for a buffer a second time. This is likely required if
// this is a different context, since otherwise the wait could be skipped
// by bouncing through another context. For the same context the extra
@@ -700,7 +676,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (SyncFeatures::getInstance().useNativeFenceSync()) {
EGLSyncKHR sync = eglCreateSyncKHR(dpy,
- EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+ EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
if (sync == EGL_NO_SYNC_KHR) {
GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
eglGetError());
@@ -744,7 +720,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
// Create a fence for the outstanding accesses in the current
// OpenGL ES context.
- fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
+ fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
if (fence == EGL_NO_SYNC_KHR) {
GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
eglGetError());
@@ -758,25 +734,6 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
return OK;
}
-bool GLConsumer::isExternalFormat(PixelFormat format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
uint32_t GLConsumer::getCurrentTextureTarget() const {
return mTexTarget;
}
@@ -795,11 +752,11 @@ void GLConsumer::setFilteringEnabled(bool enabled) {
bool needsRecompute = mFilteringEnabled != enabled;
mFilteringEnabled = enabled;
- if (needsRecompute && mCurrentTextureImage==nullptr) {
+ if (needsRecompute && mCurrentTextureImage==NULL) {
GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
}
- if (needsRecompute && mCurrentTextureImage != nullptr) {
+ if (needsRecompute && mCurrentTextureImage != NULL) {
computeCurrentTransformMatrixLocked();
}
}
@@ -820,34 +777,37 @@ void GLConsumer::computeCurrentTransformMatrixLocked() {
void GLConsumer::computeTransformMatrix(float outTransform[16],
const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
bool filtering) {
-
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
+ // Transform matrices
+ static const mat4 mtxFlipH(
+ -1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 0, 0, 1
+ );
+ static const mat4 mtxFlipV(
+ 1, 0, 0, 0,
+ 0, -1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 1, 0, 1
+ );
+ static const mat4 mtxRot90(
+ 0, 1, 0, 0,
+ -1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 1, 0, 0, 1
+ );
+
+ mat4 xform;
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxFlipH;
}
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxFlipV;
}
if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxRot90;
}
- float mtxBeforeFlipV[16];
if (!cropRect.isEmpty()) {
float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
float bufferWidth = buf->getWidth();
@@ -893,25 +853,63 @@ void GLConsumer::computeTransformMatrix(float outTransform[16],
sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
bufferHeight;
}
- float crop[16] = {
+
+ mat4 crop(
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- mtxMul(mtxBeforeFlipV, crop, xform);
- } else {
- for (int i = 0; i < 16; i++) {
- mtxBeforeFlipV[i] = xform[i];
- }
+ tx, ty, 0, 1
+ );
+ xform = crop * xform;
}
// SurfaceFlinger expects the top of its window textures to be at a Y
// coordinate of 0, so GLConsumer must behave the same way. We don't
// want to expose this to applications, however, so we must add an
// additional vertical flip to the transform after all the other transforms.
- mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
+ xform = mtxFlipV * xform;
+
+ memcpy(outTransform, xform.asArray(), sizeof(xform));
+}
+
+Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
+ Rect outCrop = crop;
+
+ uint32_t newWidth = static_cast<uint32_t>(crop.width());
+ uint32_t newHeight = static_cast<uint32_t>(crop.height());
+
+ if (newWidth * bufferHeight > newHeight * bufferWidth) {
+ newWidth = newHeight * bufferWidth / bufferHeight;
+ ALOGV("too wide: newWidth = %d", newWidth);
+ } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
+ newHeight = newWidth * bufferHeight / bufferWidth;
+ ALOGV("too tall: newHeight = %d", newHeight);
+ }
+
+ uint32_t currentWidth = static_cast<uint32_t>(crop.width());
+ uint32_t currentHeight = static_cast<uint32_t>(crop.height());
+
+ // The crop is too wide
+ if (newWidth < currentWidth) {
+ uint32_t dw = currentWidth - newWidth;
+ auto halfdw = dw / 2;
+ outCrop.left += halfdw;
+ // Not halfdw because it would subtract 1 too few when dw is odd
+ outCrop.right -= (dw - halfdw);
+ // The crop is too tall
+ } else if (newHeight < currentHeight) {
+ uint32_t dh = currentHeight - newHeight;
+ auto halfdh = dh / 2;
+ outCrop.top += halfdh;
+ // Not halfdh because it would subtract 1 too few when dh is odd
+ outCrop.bottom -= (dh - halfdh);
+ }
+
+ ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
+ outCrop.left, outCrop.top,
+ outCrop.right,outCrop.bottom);
+
+ return outCrop;
}
nsecs_t GLConsumer::getTimestamp() {
@@ -940,50 +938,14 @@ sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
}
return (mCurrentTextureImage == nullptr) ?
- nullptr : mCurrentTextureImage->graphicBuffer();
+ NULL : mCurrentTextureImage->graphicBuffer();
}
Rect GLConsumer::getCurrentCrop() const {
Mutex::Autolock lock(mMutex);
-
- Rect outCrop = mCurrentCrop;
- if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
- uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
-
- if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
- newWidth = newHeight * mDefaultWidth / mDefaultHeight;
- GLC_LOGV("too wide: newWidth = %d", newWidth);
- } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
- newHeight = newWidth * mDefaultHeight / mDefaultWidth;
- GLC_LOGV("too tall: newHeight = %d", newHeight);
- }
-
- uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
- uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
-
- // The crop is too wide
- if (newWidth < currentWidth) {
- uint32_t dw = currentWidth - newWidth;
- auto halfdw = dw / 2;
- outCrop.left += halfdw;
- // Not halfdw because it would subtract 1 too few when dw is odd
- outCrop.right -= (dw - halfdw);
- // The crop is too tall
- } else if (newHeight < currentHeight) {
- uint32_t dh = currentHeight - newHeight;
- auto halfdh = dh / 2;
- outCrop.top += halfdh;
- // Not halfdh because it would subtract 1 too few when dh is odd
- outCrop.bottom -= (dh - halfdh);
- }
-
- GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
- outCrop.left, outCrop.top,
- outCrop.right,outCrop.bottom);
- }
-
- return outCrop;
+ return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
+ ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
+ : mCurrentCrop;
}
uint32_t GLConsumer::getCurrentTransform() const {
@@ -1006,11 +968,6 @@ std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
return mCurrentFenceTime;
}
-status_t GLConsumer::doGLFenceWait() const {
- Mutex::Autolock lock(mMutex);
- return doGLFenceWaitLocked();
-}
-
status_t GLConsumer::doGLFenceWaitLocked() const {
EGLDisplay dpy = eglGetCurrentDisplay();
@@ -1027,7 +984,8 @@ status_t GLConsumer::doGLFenceWaitLocked() const {
}
if (mCurrentFence->isValid()) {
- if (SyncFeatures::getInstance().useWaitSync()) {
+ if (SyncFeatures::getInstance().useWaitSync() &&
+ SyncFeatures::getInstance().useNativeFenceSync()) {
// Create an EGLSyncKHR from the current fence.
int fenceFd = mCurrentFence->dup();
if (fenceFd == -1) {
@@ -1086,61 +1044,8 @@ void GLConsumer::abandonLocked() {
ConsumerBase::abandonLocked();
}
-void GLConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setName: GLConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
-status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
-status_t GLConsumer::setDefaultBufferDataSpace(
- android_dataspace defaultDataSpace) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
-}
-
status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
- return NO_INIT;
- }
- usage |= DEFAULT_USAGE_FLAGS;
- return mConsumer->setConsumerUsageBits(usage);
-}
-
-status_t GLConsumer::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setTransformHint(hint);
-}
-
-status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+ return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
}
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
@@ -1155,28 +1060,6 @@ void GLConsumer::dumpLocked(String8& result, const char* prefix) const
ConsumerBase::dumpLocked(result, prefix);
}
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
mGraphicBuffer(graphicBuffer),
mEglImage(EGL_NO_IMAGE_KHR),
@@ -1267,7 +1150,7 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
attrs[3] = attrs[11];
attrs[4] = EGL_NONE;
}
- eglInitialize(dpy, nullptr, nullptr);
+ eglInitialize(dpy, 0, 0);
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
if (image == EGL_NO_IMAGE_KHR) {