blob: b86e54217f97818f4990c041f1547e10fd7b3d3a [file] [log] [blame]
Chia-I Wuf1405182017-11-27 11:29:21 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#undef LOG_TAG
18#define LOG_TAG "BufferLayerConsumer"
19#define ATRACE_TAG ATRACE_TAG_GRAPHICS
20//#define LOG_NDEBUG 0
21
22#include "BufferLayerConsumer.h"
23
Chia-I Wuda5c7302017-11-27 14:51:06 -080024#include "DispSync.h"
Chia-I Wuc75c44d2017-11-27 14:32:57 -080025#include "Layer.h"
Chia-I Wu9f2db772017-11-30 21:06:50 -080026#include "RenderEngine/RenderEngine.h"
Chia-I Wuc75c44d2017-11-27 14:32:57 -080027
Chia-I Wuf1405182017-11-27 11:29:21 -080028#include <inttypes.h>
29
30#include <EGL/egl.h>
31#include <EGL/eglext.h>
32#include <GLES2/gl2.h>
33#include <GLES2/gl2ext.h>
34#include <cutils/compiler.h>
35
36#include <hardware/hardware.h>
37
38#include <math/mat4.h>
39
40#include <gui/BufferItem.h>
41#include <gui/GLConsumer.h>
42#include <gui/ISurfaceComposer.h>
43#include <gui/SurfaceComposerClient.h>
44
45#include <private/gui/ComposerService.h>
46#include <private/gui/SyncFeatures.h>
47
48#include <utils/Log.h>
49#include <utils/String8.h>
50#include <utils/Trace.h>
51
52extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
53#define CROP_EXT_STR "EGL_ANDROID_image_crop"
54#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
55#define EGL_PROTECTED_CONTENT_EXT 0x32C0
56
57namespace android {
58
59// Macros for including the BufferLayerConsumer name in log messages
60#define BLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
61#define BLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
62//#define BLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
63#define BLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
64#define BLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
65
Chia-I Wuf1405182017-11-27 11:29:21 -080066static const mat4 mtxIdentity;
67
Chia-I Wuf1405182017-11-27 11:29:21 -080068static bool hasEglAndroidImageCropImpl() {
69 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
70 const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
71 size_t cropExtLen = strlen(CROP_EXT_STR);
72 size_t extsLen = strlen(exts);
73 bool equal = !strcmp(CROP_EXT_STR, exts);
74 bool atStart = !strncmp(CROP_EXT_STR " ", exts, cropExtLen + 1);
75 bool atEnd = (cropExtLen + 1) < extsLen &&
76 !strcmp(" " CROP_EXT_STR, exts + extsLen - (cropExtLen + 1));
77 bool inMiddle = strstr(exts, " " CROP_EXT_STR " ");
78 return equal || atStart || atEnd || inMiddle;
79}
80
81static bool hasEglAndroidImageCrop() {
82 // Only compute whether the extension is present once the first time this
83 // function is called.
84 static bool hasIt = hasEglAndroidImageCropImpl();
85 return hasIt;
86}
87
88static bool hasEglProtectedContentImpl() {
89 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
90 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
91 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
92 size_t extsLen = strlen(exts);
93 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
94 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen + 1);
95 bool atEnd = (cropExtLen + 1) < extsLen &&
96 !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen + 1));
97 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
98 return equal || atStart || atEnd || inMiddle;
99}
100
101static bool hasEglProtectedContent() {
102 // Only compute whether the extension is present once the first time this
103 // function is called.
104 static bool hasIt = hasEglProtectedContentImpl();
105 return hasIt;
106}
107
108static bool isEglImageCroppable(const Rect& crop) {
109 return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
110}
111
Chia-I Wu9f2db772017-11-30 21:06:50 -0800112BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine,
113 uint32_t tex, Layer* layer)
Chia-I Wubd854bf2017-11-27 13:41:26 -0800114 : ConsumerBase(bq, false),
Chia-I Wuf1405182017-11-27 11:29:21 -0800115 mCurrentCrop(Rect::EMPTY_RECT),
116 mCurrentTransform(0),
117 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
118 mCurrentFence(Fence::NO_FENCE),
119 mCurrentTimestamp(0),
120 mCurrentDataSpace(HAL_DATASPACE_UNKNOWN),
121 mCurrentFrameNumber(0),
Chia-I Wu67dcc692017-11-27 14:51:06 -0800122 mCurrentTransformToDisplayInverse(false),
123 mCurrentSurfaceDamage(),
Chia-I Wuf1405182017-11-27 11:29:21 -0800124 mDefaultWidth(1),
125 mDefaultHeight(1),
126 mFilteringEnabled(true),
Chia-I Wu9f2db772017-11-30 21:06:50 -0800127 mRE(engine),
128 mEglDisplay(mRE.getEGLDisplay()),
Chia-I Wuf1405182017-11-27 11:29:21 -0800129 mTexName(tex),
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800130 mLayer(layer),
Chia-I Wuc91077c2017-11-27 13:32:04 -0800131 mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800132 BLC_LOGV("BufferLayerConsumer");
133
134 memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
135
136 mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
137}
138
139status_t BufferLayerConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) {
140 Mutex::Autolock lock(mMutex);
141 if (mAbandoned) {
142 BLC_LOGE("setDefaultBufferSize: BufferLayerConsumer is abandoned!");
143 return NO_INIT;
144 }
145 mDefaultWidth = w;
146 mDefaultHeight = h;
147 return mConsumer->setDefaultBufferSize(w, h);
148}
149
Chia-I Wufd257f82017-11-27 14:51:06 -0800150void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
151 setFrameAvailableListener(listener);
152 Mutex::Autolock lock(mMutex);
153 mContentsChangedListener = listener;
154}
155
Chia-I Wuda5c7302017-11-27 14:51:06 -0800156// We need to determine the time when a buffer acquired now will be
157// displayed. This can be calculated:
158// time when previous buffer's actual-present fence was signaled
159// + current display refresh rate * HWC latency
160// + a little extra padding
161//
162// Buffer producers are expected to set their desired presentation time
163// based on choreographer time stamps, which (coming from vsync events)
164// will be slightly later then the actual-present timing. If we get a
165// desired-present time that is unintentionally a hair after the next
166// vsync, we'll hold the frame when we really want to display it. We
167// need to take the offset between actual-present and reported-vsync
168// into account.
169//
170// If the system is configured without a DispSync phase offset for the app,
171// we also want to throw in a bit of padding to avoid edge cases where we
172// just barely miss. We want to do it here, not in every app. A major
173// source of trouble is the app's use of the display's ideal refresh time
174// (via Display.getRefreshRate()), which could be off of the actual refresh
175// by a few percent, with the error multiplied by the number of frames
176// between now and when the buffer should be displayed.
177//
178// If the refresh reported to the app has a phase offset, we shouldn't need
179// to tweak anything here.
180nsecs_t BufferLayerConsumer::computeExpectedPresent(const DispSync& dispSync) {
181 // The HWC doesn't currently have a way to report additional latency.
182 // Assume that whatever we submit now will appear right after the flip.
183 // For a smart panel this might be 1. This is expressed in frames,
184 // rather than time, because we expect to have a constant frame delay
185 // regardless of the refresh rate.
186 const uint32_t hwcLatency = 0;
187
188 // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
189 const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);
190
191 // The DispSync time is already adjusted for the difference between
192 // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
193 // we don't need to factor that in here. Pad a little to avoid
194 // weird effects if apps might be requesting times right on the edge.
195 nsecs_t extraPadding = 0;
196 if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
197 extraPadding = 1000000; // 1ms (6% of 60Hz)
198 }
199
200 return nextRefresh + extraPadding;
201}
202
203status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
204 bool* autoRefresh, bool* queuedBuffer,
205 uint64_t maxFrameNumber) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800206 ATRACE_CALL();
207 BLC_LOGV("updateTexImage");
208 Mutex::Autolock lock(mMutex);
209
210 if (mAbandoned) {
211 BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!");
212 return NO_INIT;
213 }
214
Chia-I Wu9f2db772017-11-30 21:06:50 -0800215 // Make sure RenderEngine is current
216 if (!mRE.isCurrent()) {
217 BLC_LOGE("updateTexImage: RenderEngine is not current");
218 return INVALID_OPERATION;
Chia-I Wuf1405182017-11-27 11:29:21 -0800219 }
220
221 BufferItem item;
222
223 // Acquire the next buffer.
224 // In asynchronous mode the list is guaranteed to be one buffer
225 // deep, while in synchronous mode we use the oldest buffer.
Chia-I Wu9f2db772017-11-30 21:06:50 -0800226 status_t err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
Chia-I Wuf1405182017-11-27 11:29:21 -0800227 if (err != NO_ERROR) {
228 if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800229 err = NO_ERROR;
Chia-I Wuda5c7302017-11-27 14:51:06 -0800230 } else if (err == BufferQueue::PRESENT_LATER) {
231 // return the error, without logging
Chia-I Wuf1405182017-11-27 11:29:21 -0800232 } else {
233 BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
234 }
235 return err;
236 }
237
Chia-I Wuda5c7302017-11-27 14:51:06 -0800238 if (autoRefresh) {
239 *autoRefresh = item.mAutoRefresh;
240 }
241
242 if (queuedBuffer) {
243 *queuedBuffer = item.mQueuedBuffer;
244 }
245
246 // We call the rejecter here, in case the caller has a reason to
247 // not accept this buffer. This is used by SurfaceFlinger to
248 // reject buffers which have the wrong size
249 int slot = item.mSlot;
250 if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
251 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
252 return BUFFER_REJECTED;
253 }
254
Chia-I Wuf1405182017-11-27 11:29:21 -0800255 // Release the previous buffer.
Chia-I Wuda5c7302017-11-27 14:51:06 -0800256 err = updateAndReleaseLocked(item, &mPendingRelease);
Chia-I Wuf1405182017-11-27 11:29:21 -0800257 if (err != NO_ERROR) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800258 return err;
259 }
260
Chia-I Wuda5c7302017-11-27 14:51:06 -0800261 if (!SyncFeatures::getInstance().useNativeFenceSync()) {
262 // Bind the new buffer to the GL texture.
263 //
264 // Older devices require the "implicit" synchronization provided
265 // by glEGLImageTargetTexture2DOES, which this method calls. Newer
266 // devices will either call this in Layer::onDraw, or (if it's not
267 // a GL-composited layer) not at all.
268 err = bindTextureImageLocked();
269 }
270
271 return err;
272}
273
Chia-I Wu0cb75ac2017-11-27 15:56:04 -0800274status_t BufferLayerConsumer::bindTextureImage() {
275 Mutex::Autolock lock(mMutex);
276 return bindTextureImageLocked();
277}
278
Chia-I Wuda5c7302017-11-27 14:51:06 -0800279void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
280 if (!fence->isValid()) {
281 return;
282 }
283
284 auto slot = mPendingRelease.isPending ? mPendingRelease.currentTexture : mCurrentTexture;
285 if (slot == BufferQueue::INVALID_BUFFER_SLOT) {
286 return;
287 }
288
289 auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer
290 : mCurrentTextureImage->graphicBuffer();
291 auto err = addReleaseFence(slot, buffer, fence);
292 if (err != OK) {
293 BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
294 }
295}
296
297bool BufferLayerConsumer::releasePendingBuffer() {
298 if (!mPendingRelease.isPending) {
299 BLC_LOGV("Pending buffer already released");
300 return false;
301 }
302 BLC_LOGV("Releasing pending buffer");
303 Mutex::Autolock lock(mMutex);
304 status_t result =
305 releaseBufferLocked(mPendingRelease.currentTexture, mPendingRelease.graphicBuffer);
306 if (result < NO_ERROR) {
307 BLC_LOGE("releasePendingBuffer failed: %s (%d)", strerror(-result), result);
308 }
309 mPendingRelease = PendingRelease();
310 return true;
Chia-I Wuf1405182017-11-27 11:29:21 -0800311}
312
Chia-I Wu0cb75ac2017-11-27 15:56:04 -0800313sp<Fence> BufferLayerConsumer::getPrevFinalReleaseFence() const {
314 Mutex::Autolock lock(mMutex);
315 return ConsumerBase::mPrevFinalReleaseFence;
316}
317
Chia-I Wuf1405182017-11-27 11:29:21 -0800318status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
319 uint64_t maxFrameNumber) {
320 status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
321 if (err != NO_ERROR) {
322 return err;
323 }
324
325 // If item->mGraphicBuffer is not null, this buffer has not been acquired
326 // before, so any prior EglImage created is using a stale buffer. This
327 // replaces any old EglImage with a new one (using the new buffer).
328 if (item->mGraphicBuffer != NULL) {
329 int slot = item->mSlot;
330 mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
331 }
332
333 return NO_ERROR;
334}
335
Chia-I Wuf1405182017-11-27 11:29:21 -0800336status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
337 PendingRelease* pendingRelease) {
338 status_t err = NO_ERROR;
339
340 int slot = item.mSlot;
341
Chia-I Wuf1405182017-11-27 11:29:21 -0800342 // Ensure we have a valid EglImageKHR for the slot, creating an EglImage
343 // if nessessary, for the gralloc buffer currently in the slot in
344 // ConsumerBase.
345 // We may have to do this even when item.mGraphicBuffer == NULL (which
346 // means the buffer was previously acquired).
347 err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
348 if (err != NO_ERROR) {
349 BLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay,
350 slot);
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800351 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800352 return UNKNOWN_ERROR;
353 }
354
355 // Do whatever sync ops we need to do before releasing the old slot.
356 if (slot != mCurrentTexture) {
357 err = syncForReleaseLocked(mEglDisplay);
358 if (err != NO_ERROR) {
359 // Release the buffer we just acquired. It's not safe to
360 // release the old buffer, so instead we just drop the new frame.
361 // As we are still under lock since acquireBuffer, it is safe to
362 // release by slot.
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800363 releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
Chia-I Wuf1405182017-11-27 11:29:21 -0800364 return err;
365 }
366 }
367
368 BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
369 mCurrentTextureImage != NULL ? mCurrentTextureImage->graphicBufferHandle() : 0, slot,
370 mSlots[slot].mGraphicBuffer->handle);
371
372 // Hang onto the pointer so that it isn't freed in the call to
373 // releaseBufferLocked() if we're in shared buffer mode and both buffers are
374 // the same.
375 sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
376
377 // release old buffer
378 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
379 if (pendingRelease == nullptr) {
380 status_t status =
Chia-I Wu6aff69b2017-11-27 14:08:48 -0800381 releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
Chia-I Wuf1405182017-11-27 11:29:21 -0800382 if (status < NO_ERROR) {
383 BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
384 status);
385 err = status;
386 // keep going, with error raised [?]
387 }
388 } else {
389 pendingRelease->currentTexture = mCurrentTexture;
390 pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
Chia-I Wuf1405182017-11-27 11:29:21 -0800391 pendingRelease->isPending = true;
392 }
393 }
394
395 // Update the BufferLayerConsumer state.
396 mCurrentTexture = slot;
397 mCurrentTextureImage = nextTextureImage;
398 mCurrentCrop = item.mCrop;
399 mCurrentTransform = item.mTransform;
400 mCurrentScalingMode = item.mScalingMode;
401 mCurrentTimestamp = item.mTimestamp;
402 mCurrentDataSpace = item.mDataSpace;
403 mCurrentFence = item.mFence;
404 mCurrentFenceTime = item.mFenceTime;
405 mCurrentFrameNumber = item.mFrameNumber;
Chia-I Wu67dcc692017-11-27 14:51:06 -0800406 mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
407 mCurrentSurfaceDamage = item.mSurfaceDamage;
Chia-I Wuf1405182017-11-27 11:29:21 -0800408
409 computeCurrentTransformMatrixLocked();
410
411 return err;
412}
413
414status_t BufferLayerConsumer::bindTextureImageLocked() {
Chia-I Wu9f2db772017-11-30 21:06:50 -0800415 mRE.checkErrors();
Chia-I Wuf1405182017-11-27 11:29:21 -0800416
Chia-I Wubd854bf2017-11-27 13:41:26 -0800417 glBindTexture(sTexTarget, mTexName);
Chia-I Wuf1405182017-11-27 11:29:21 -0800418 if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == NULL) {
419 BLC_LOGE("bindTextureImage: no currently-bound texture");
420 return NO_INIT;
421 }
422
423 status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, mCurrentCrop);
424 if (err != NO_ERROR) {
425 BLC_LOGW("bindTextureImage: can't create image on display=%p slot=%d", mEglDisplay,
426 mCurrentTexture);
427 return UNKNOWN_ERROR;
428 }
Chia-I Wubd854bf2017-11-27 13:41:26 -0800429 mCurrentTextureImage->bindToTextureTarget(sTexTarget);
Chia-I Wuf1405182017-11-27 11:29:21 -0800430
Chia-I Wuf1405182017-11-27 11:29:21 -0800431 // Wait for the new buffer to be ready.
432 return doGLFenceWaitLocked();
433}
434
Chia-I Wuf1405182017-11-27 11:29:21 -0800435status_t BufferLayerConsumer::syncForReleaseLocked(EGLDisplay dpy) {
436 BLC_LOGV("syncForReleaseLocked");
437
438 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
439 if (SyncFeatures::getInstance().useNativeFenceSync()) {
440 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
441 if (sync == EGL_NO_SYNC_KHR) {
442 BLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x", eglGetError());
443 return UNKNOWN_ERROR;
444 }
445 glFlush();
446 int fenceFd = eglDupNativeFenceFDANDROID(dpy, sync);
447 eglDestroySyncKHR(dpy, sync);
448 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
449 BLC_LOGE("syncForReleaseLocked: error dup'ing native fence "
450 "fd: %#x",
451 eglGetError());
452 return UNKNOWN_ERROR;
453 }
454 sp<Fence> fence(new Fence(fenceFd));
455 status_t err = addReleaseFenceLocked(mCurrentTexture,
456 mCurrentTextureImage->graphicBuffer(), fence);
457 if (err != OK) {
458 BLC_LOGE("syncForReleaseLocked: error adding release fence: "
459 "%s (%d)",
460 strerror(-err), err);
461 return err;
462 }
Chia-I Wuf1405182017-11-27 11:29:21 -0800463 }
464 }
465
466 return OK;
467}
468
Chia-I Wuf1405182017-11-27 11:29:21 -0800469void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
470 Mutex::Autolock lock(mMutex);
471 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
472}
473
474void BufferLayerConsumer::setFilteringEnabled(bool enabled) {
475 Mutex::Autolock lock(mMutex);
476 if (mAbandoned) {
477 BLC_LOGE("setFilteringEnabled: BufferLayerConsumer is abandoned!");
478 return;
479 }
480 bool needsRecompute = mFilteringEnabled != enabled;
481 mFilteringEnabled = enabled;
482
483 if (needsRecompute && mCurrentTextureImage == NULL) {
484 BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
485 }
486
487 if (needsRecompute && mCurrentTextureImage != NULL) {
488 computeCurrentTransformMatrixLocked();
489 }
490}
491
492void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
493 BLC_LOGV("computeCurrentTransformMatrixLocked");
494 sp<GraphicBuffer> buf =
495 (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
496 if (buf == nullptr) {
497 BLC_LOGD("computeCurrentTransformMatrixLocked: "
498 "mCurrentTextureImage is NULL");
499 }
Chia-I Wu243b74a2017-11-27 14:24:14 -0800500 GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf,
501 isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT
502 : mCurrentCrop,
503 mCurrentTransform, mFilteringEnabled);
Chia-I Wuf1405182017-11-27 11:29:21 -0800504}
505
Chia-I Wuf1405182017-11-27 11:29:21 -0800506nsecs_t BufferLayerConsumer::getTimestamp() {
507 BLC_LOGV("getTimestamp");
508 Mutex::Autolock lock(mMutex);
509 return mCurrentTimestamp;
510}
511
512android_dataspace BufferLayerConsumer::getCurrentDataSpace() {
513 BLC_LOGV("getCurrentDataSpace");
514 Mutex::Autolock lock(mMutex);
515 return mCurrentDataSpace;
516}
517
518uint64_t BufferLayerConsumer::getFrameNumber() {
519 BLC_LOGV("getFrameNumber");
520 Mutex::Autolock lock(mMutex);
521 return mCurrentFrameNumber;
522}
523
Chia-I Wu67dcc692017-11-27 14:51:06 -0800524bool BufferLayerConsumer::getTransformToDisplayInverse() const {
525 Mutex::Autolock lock(mMutex);
526 return mCurrentTransformToDisplayInverse;
527}
528
529const Region& BufferLayerConsumer::getSurfaceDamage() const {
530 return mCurrentSurfaceDamage;
531}
532
Chia-I Wuf1405182017-11-27 11:29:21 -0800533sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
534 Mutex::Autolock lock(mMutex);
535
536 if (outSlot != nullptr) {
537 *outSlot = mCurrentTexture;
538 }
539
540 return (mCurrentTextureImage == nullptr) ? NULL : mCurrentTextureImage->graphicBuffer();
541}
542
543Rect BufferLayerConsumer::getCurrentCrop() const {
544 Mutex::Autolock lock(mMutex);
545 return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
Chia-I Wue1e11872017-12-01 09:21:59 -0800546 ? GLConsumer::scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
Chia-I Wuf1405182017-11-27 11:29:21 -0800547 : mCurrentCrop;
548}
549
550uint32_t BufferLayerConsumer::getCurrentTransform() const {
551 Mutex::Autolock lock(mMutex);
552 return mCurrentTransform;
553}
554
555uint32_t BufferLayerConsumer::getCurrentScalingMode() const {
556 Mutex::Autolock lock(mMutex);
557 return mCurrentScalingMode;
558}
559
560sp<Fence> BufferLayerConsumer::getCurrentFence() const {
561 Mutex::Autolock lock(mMutex);
562 return mCurrentFence;
563}
564
565std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
566 Mutex::Autolock lock(mMutex);
567 return mCurrentFenceTime;
568}
569
570status_t BufferLayerConsumer::doGLFenceWaitLocked() const {
Chia-I Wu9f2db772017-11-30 21:06:50 -0800571 if (!mRE.isCurrent()) {
572 BLC_LOGE("doGLFenceWait: RenderEngine is not current");
Chia-I Wuf1405182017-11-27 11:29:21 -0800573 return INVALID_OPERATION;
574 }
575
576 if (mCurrentFence->isValid()) {
577 if (SyncFeatures::getInstance().useWaitSync()) {
578 // Create an EGLSyncKHR from the current fence.
579 int fenceFd = mCurrentFence->dup();
580 if (fenceFd == -1) {
581 BLC_LOGE("doGLFenceWait: error dup'ing fence fd: %d", errno);
582 return -errno;
583 }
584 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
Chia-I Wu9f2db772017-11-30 21:06:50 -0800585 EGLSyncKHR sync = eglCreateSyncKHR(mEglDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
Chia-I Wuf1405182017-11-27 11:29:21 -0800586 if (sync == EGL_NO_SYNC_KHR) {
587 close(fenceFd);
588 BLC_LOGE("doGLFenceWait: error creating EGL fence: %#x", eglGetError());
589 return UNKNOWN_ERROR;
590 }
591
592 // XXX: The spec draft is inconsistent as to whether this should
593 // return an EGLint or void. Ignore the return value for now, as
594 // it's not strictly needed.
Chia-I Wu9f2db772017-11-30 21:06:50 -0800595 eglWaitSyncKHR(mEglDisplay, sync, 0);
Chia-I Wuf1405182017-11-27 11:29:21 -0800596 EGLint eglErr = eglGetError();
Chia-I Wu9f2db772017-11-30 21:06:50 -0800597 eglDestroySyncKHR(mEglDisplay, sync);
Chia-I Wuf1405182017-11-27 11:29:21 -0800598 if (eglErr != EGL_SUCCESS) {
599 BLC_LOGE("doGLFenceWait: error waiting for EGL fence: %#x", eglErr);
600 return UNKNOWN_ERROR;
601 }
602 } else {
603 status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doGLFenceWaitLocked");
604 if (err != NO_ERROR) {
605 BLC_LOGE("doGLFenceWait: error waiting for fence: %d", err);
606 return err;
607 }
608 }
609 }
610
611 return NO_ERROR;
612}
613
614void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
615 BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
616 if (slotIndex == mCurrentTexture) {
617 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
618 }
619 mEglSlots[slotIndex].mEglImage.clear();
620 ConsumerBase::freeBufferLocked(slotIndex);
621}
622
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800623void BufferLayerConsumer::onDisconnect() {
624 sp<Layer> l = mLayer.promote();
625 if (l.get()) {
626 l->onDisconnect();
627 }
628}
629
Chia-I Wufd257f82017-11-27 14:51:06 -0800630void BufferLayerConsumer::onSidebandStreamChanged() {
631 FrameAvailableListener* unsafeFrameAvailableListener = nullptr;
632 {
633 Mutex::Autolock lock(mFrameAvailableMutex);
634 unsafeFrameAvailableListener = mFrameAvailableListener.unsafe_get();
635 }
636 sp<ContentsChangedListener> listener;
637 { // scope for the lock
638 Mutex::Autolock lock(mMutex);
639 ALOG_ASSERT(unsafeFrameAvailableListener == mContentsChangedListener.unsafe_get());
640 listener = mContentsChangedListener.promote();
641 }
642
643 if (listener != NULL) {
644 listener->onSidebandStreamChanged();
645 }
646}
647
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800648void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
649 FrameEventHistoryDelta* outDelta) {
650 sp<Layer> l = mLayer.promote();
651 if (l.get()) {
652 l->addAndGetFrameTimestamps(newTimestamps, outDelta);
653 }
654}
655
Chia-I Wuf1405182017-11-27 11:29:21 -0800656void BufferLayerConsumer::abandonLocked() {
657 BLC_LOGV("abandonLocked");
658 mCurrentTextureImage.clear();
659 ConsumerBase::abandonLocked();
660}
661
662status_t BufferLayerConsumer::setConsumerUsageBits(uint64_t usage) {
663 return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
664}
665
666void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const {
667 result.appendFormat("%smTexName=%d mCurrentTexture=%d\n"
668 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
669 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
670 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
671 mCurrentTransform);
672
673 ConsumerBase::dumpLocked(result, prefix);
674}
675
676BufferLayerConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
677 : mGraphicBuffer(graphicBuffer),
678 mEglImage(EGL_NO_IMAGE_KHR),
679 mEglDisplay(EGL_NO_DISPLAY),
680 mCropRect(Rect::EMPTY_RECT) {}
681
682BufferLayerConsumer::EglImage::~EglImage() {
683 if (mEglImage != EGL_NO_IMAGE_KHR) {
684 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
685 ALOGE("~EglImage: eglDestroyImageKHR failed");
686 }
687 eglTerminate(mEglDisplay);
688 }
689}
690
Chia-I Wuc91077c2017-11-27 13:32:04 -0800691status_t BufferLayerConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
692 const Rect& cropRect) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800693 // If there's an image and it's no longer valid, destroy it.
694 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
695 bool displayInvalid = mEglDisplay != eglDisplay;
696 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
Chia-I Wuc91077c2017-11-27 13:32:04 -0800697 if (haveImage && (displayInvalid || cropInvalid)) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800698 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
699 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
700 }
701 eglTerminate(mEglDisplay);
702 mEglImage = EGL_NO_IMAGE_KHR;
703 mEglDisplay = EGL_NO_DISPLAY;
704 }
705
706 // If there's no image, create one.
707 if (mEglImage == EGL_NO_IMAGE_KHR) {
708 mEglDisplay = eglDisplay;
709 mCropRect = cropRect;
710 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
711 }
712
713 // Fail if we can't create a valid image.
714 if (mEglImage == EGL_NO_IMAGE_KHR) {
715 mEglDisplay = EGL_NO_DISPLAY;
716 mCropRect.makeInvalid();
717 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
718 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
719 buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
720 buffer->getPixelFormat());
721 return UNKNOWN_ERROR;
722 }
723
724 return OK;
725}
726
727void BufferLayerConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
728 glEGLImageTargetTexture2DOES(texTarget, static_cast<GLeglImageOES>(mEglImage));
729}
730
731EGLImageKHR BufferLayerConsumer::EglImage::createImage(EGLDisplay dpy,
732 const sp<GraphicBuffer>& graphicBuffer,
733 const Rect& crop) {
734 EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
735 const bool createProtectedImage =
736 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent();
737 EGLint attrs[] = {
738 EGL_IMAGE_PRESERVED_KHR,
739 EGL_TRUE,
740 EGL_IMAGE_CROP_LEFT_ANDROID,
741 crop.left,
742 EGL_IMAGE_CROP_TOP_ANDROID,
743 crop.top,
744 EGL_IMAGE_CROP_RIGHT_ANDROID,
745 crop.right,
746 EGL_IMAGE_CROP_BOTTOM_ANDROID,
747 crop.bottom,
748 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
749 createProtectedImage ? EGL_TRUE : EGL_NONE,
750 EGL_NONE,
751 };
752 if (!crop.isValid()) {
753 // No crop rect to set, so leave the crop out of the attrib array. Make
754 // sure to propagate the protected content attrs if they are set.
755 attrs[2] = attrs[10];
756 attrs[3] = attrs[11];
757 attrs[4] = EGL_NONE;
758 } else if (!isEglImageCroppable(crop)) {
759 // The crop rect is not at the origin, so we can't set the crop on the
760 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
761 // extension. In the future we can add a layered extension that
762 // removes this restriction if there is hardware that can support it.
763 attrs[2] = attrs[10];
764 attrs[3] = attrs[11];
765 attrs[4] = EGL_NONE;
766 }
767 eglInitialize(dpy, 0, 0);
768 EGLImageKHR image =
769 eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
770 if (image == EGL_NO_IMAGE_KHR) {
771 EGLint error = eglGetError();
772 ALOGE("error creating EGLImage: %#x", error);
773 eglTerminate(dpy);
774 }
775 return image;
776}
777
778}; // namespace android