mUserWidth = 0;
mUserHeight = 0;
mTransformHint = 0;
+ mConsumerRunningBehind = false;
mConnectedToCpu = false;
}
result);
return result;
}
- sp<GraphicBuffer>& gbuf(mSlots[buf]);
+ sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
}
android_native_buffer_t* buffer) const {
bool dumpedState = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) {
+ if (mSlots[i].buffer != NULL &&
+ mSlots[i].buffer->handle == buffer->handle) {
return i;
}
}
return i;
}
+ // Make sure the crop rectangle is entirely inside the buffer.
+ Rect crop;
+ mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
+
ISurfaceTexture::QueueBufferOutput output;
- ISurfaceTexture::QueueBufferInput input(timestamp,
- mCrop, mScalingMode, mTransform);
+ ISurfaceTexture::QueueBufferInput input(timestamp, crop, mScalingMode,
+ mTransform);
status_t err = mSurfaceTexture->queueBuffer(i, input, &output);
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
}
- output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint);
+ uint32_t numPendingBuffers = 0;
+ output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
+ &numPendingBuffers);
+
+ mConsumerRunningBehind = (numPendingBuffers >= 2);
+
return err;
}
return NO_ERROR;
}
break;
- case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
- {
- sp<ISurfaceComposer> composer(
- ComposerService::getComposerService());
- if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
- *value = 1;
- } else {
- *value = 0;
- }
+ case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
+ sp<ISurfaceComposer> composer(
+ ComposerService::getComposerService());
+ if (composer->authenticateSurfaceTexture(mSurfaceTexture)) {
+ *value = 1;
+ } else {
+ *value = 0;
}
return NO_ERROR;
+ }
case NATIVE_WINDOW_CONCRETE_TYPE:
*value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
return NO_ERROR;
case NATIVE_WINDOW_TRANSFORM_HINT:
*value = mTransformHint;
return NO_ERROR;
+ case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
+ status_t err = NO_ERROR;
+ if (!mConsumerRunningBehind) {
+ *value = 0;
+ } else {
+ err = mSurfaceTexture->query(what, value);
+ if (err == NO_ERROR) {
+ mConsumerRunningBehind = *value;
+ }
+ }
+ return err;
+ }
}
}
return mSurfaceTexture->query(what, value);
ATRACE_CALL();
ALOGV("SurfaceTextureClient::connect");
Mutex::Autolock lock(mMutex);
- int err = mSurfaceTexture->connect(api,
- &mDefaultWidth, &mDefaultHeight, &mTransformHint);
+ ISurfaceTexture::QueueBufferOutput output;
+ int err = mSurfaceTexture->connect(api, &output);
+ if (err == NO_ERROR) {
+ uint32_t numPendingBuffers = 0;
+ output.deflate(&mDefaultWidth, &mDefaultHeight, &mTransformHint,
+ &numPendingBuffers);
+ mConsumerRunningBehind = (numPendingBuffers >= 2);
+ }
if (!err && api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = true;
}
int SurfaceTextureClient::setCrop(Rect const* rect)
{
ATRACE_CALL();
- ALOGV("SurfaceTextureClient::setCrop");
Rect realRect;
if (rect == NULL || rect->isEmpty()) {
realRect = *rect;
}
+ ALOGV("SurfaceTextureClient::setCrop rect=[%d %d %d %d]",
+ realRect.left, realRect.top, realRect.right, realRect.bottom);
+
Mutex::Autolock lock(mMutex);
- mCrop = *rect;
+ mCrop = realRect;
return NO_ERROR;
}
Mutex::Autolock lock(mMutex);
mReqWidth = w;
mReqHeight = h;
- mCrop.clear();
return NO_ERROR;
}
Mutex::Autolock lock(mMutex);
mUserWidth = w;
mUserHeight = h;
- mCrop.clear();
return NO_ERROR;
}
void SurfaceTextureClient::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i] = 0;
+ mSlots[i].buffer = 0;
}
}
if (canCopyBack) {
// copy the area that is invalid and not repainted this round
- const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));
+ const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback);
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds);
+ mDirtyRegion.clear();
+ Mutex::Autolock lock(mMutex);
+ for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
+ mSlots[i].dirtyRegion.clear();
+ }
}
- // keep track of the are of the buffer that is "clean"
- // (ie: that will be redrawn)
- mOldDirtyRegion = newDirtyRegion;
+ { // scope for the lock
+ Mutex::Autolock lock(mMutex);
+ int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
+ if (backBufferSlot >= 0) {
+ Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
+ mDirtyRegion.subtract(dirtyRegion);
+ dirtyRegion = newDirtyRegion;
+ }
+ }
+
+ mDirtyRegion.orSelf(newDirtyRegion);
if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds();
}