blob: fb6fa0301b8026707cd4344779e294471e57e34e [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) {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800357 err = syncForReleaseLocked();
Chia-I Wuf1405182017-11-27 11:29:21 -0800358 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.
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800432 return doFenceWaitLocked();
Chia-I Wuf1405182017-11-27 11:29:21 -0800433}
434
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800435status_t BufferLayerConsumer::syncForReleaseLocked() {
Chia-I Wuf1405182017-11-27 11:29:21 -0800436 BLC_LOGV("syncForReleaseLocked");
437
438 if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
439 if (SyncFeatures::getInstance().useNativeFenceSync()) {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800440 base::unique_fd fenceFd = mRE.flush();
441 if (fenceFd == -1) {
442 BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
Chia-I Wuf1405182017-11-27 11:29:21 -0800443 return UNKNOWN_ERROR;
444 }
445 sp<Fence> fence(new Fence(fenceFd));
446 status_t err = addReleaseFenceLocked(mCurrentTexture,
447 mCurrentTextureImage->graphicBuffer(), fence);
448 if (err != OK) {
449 BLC_LOGE("syncForReleaseLocked: error adding release fence: "
450 "%s (%d)",
451 strerror(-err), err);
452 return err;
453 }
Chia-I Wuf1405182017-11-27 11:29:21 -0800454 }
455 }
456
457 return OK;
458}
459
Chia-I Wuf1405182017-11-27 11:29:21 -0800460void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
461 Mutex::Autolock lock(mMutex);
462 memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
463}
464
465void BufferLayerConsumer::setFilteringEnabled(bool enabled) {
466 Mutex::Autolock lock(mMutex);
467 if (mAbandoned) {
468 BLC_LOGE("setFilteringEnabled: BufferLayerConsumer is abandoned!");
469 return;
470 }
471 bool needsRecompute = mFilteringEnabled != enabled;
472 mFilteringEnabled = enabled;
473
474 if (needsRecompute && mCurrentTextureImage == NULL) {
475 BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
476 }
477
478 if (needsRecompute && mCurrentTextureImage != NULL) {
479 computeCurrentTransformMatrixLocked();
480 }
481}
482
483void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
484 BLC_LOGV("computeCurrentTransformMatrixLocked");
485 sp<GraphicBuffer> buf =
486 (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
487 if (buf == nullptr) {
488 BLC_LOGD("computeCurrentTransformMatrixLocked: "
489 "mCurrentTextureImage is NULL");
490 }
Chia-I Wu243b74a2017-11-27 14:24:14 -0800491 GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf,
492 isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT
493 : mCurrentCrop,
494 mCurrentTransform, mFilteringEnabled);
Chia-I Wuf1405182017-11-27 11:29:21 -0800495}
496
Chia-I Wuf1405182017-11-27 11:29:21 -0800497nsecs_t BufferLayerConsumer::getTimestamp() {
498 BLC_LOGV("getTimestamp");
499 Mutex::Autolock lock(mMutex);
500 return mCurrentTimestamp;
501}
502
503android_dataspace BufferLayerConsumer::getCurrentDataSpace() {
504 BLC_LOGV("getCurrentDataSpace");
505 Mutex::Autolock lock(mMutex);
506 return mCurrentDataSpace;
507}
508
509uint64_t BufferLayerConsumer::getFrameNumber() {
510 BLC_LOGV("getFrameNumber");
511 Mutex::Autolock lock(mMutex);
512 return mCurrentFrameNumber;
513}
514
Chia-I Wu67dcc692017-11-27 14:51:06 -0800515bool BufferLayerConsumer::getTransformToDisplayInverse() const {
516 Mutex::Autolock lock(mMutex);
517 return mCurrentTransformToDisplayInverse;
518}
519
520const Region& BufferLayerConsumer::getSurfaceDamage() const {
521 return mCurrentSurfaceDamage;
522}
523
Chia-I Wuf1405182017-11-27 11:29:21 -0800524sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
525 Mutex::Autolock lock(mMutex);
526
527 if (outSlot != nullptr) {
528 *outSlot = mCurrentTexture;
529 }
530
531 return (mCurrentTextureImage == nullptr) ? NULL : mCurrentTextureImage->graphicBuffer();
532}
533
534Rect BufferLayerConsumer::getCurrentCrop() const {
535 Mutex::Autolock lock(mMutex);
536 return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
Chia-I Wue1e11872017-12-01 09:21:59 -0800537 ? GLConsumer::scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
Chia-I Wuf1405182017-11-27 11:29:21 -0800538 : mCurrentCrop;
539}
540
541uint32_t BufferLayerConsumer::getCurrentTransform() const {
542 Mutex::Autolock lock(mMutex);
543 return mCurrentTransform;
544}
545
546uint32_t BufferLayerConsumer::getCurrentScalingMode() const {
547 Mutex::Autolock lock(mMutex);
548 return mCurrentScalingMode;
549}
550
551sp<Fence> BufferLayerConsumer::getCurrentFence() const {
552 Mutex::Autolock lock(mMutex);
553 return mCurrentFence;
554}
555
556std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
557 Mutex::Autolock lock(mMutex);
558 return mCurrentFenceTime;
559}
560
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800561status_t BufferLayerConsumer::doFenceWaitLocked() const {
Chia-I Wu9f2db772017-11-30 21:06:50 -0800562 if (!mRE.isCurrent()) {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800563 BLC_LOGE("doFenceWait: RenderEngine is not current");
Chia-I Wuf1405182017-11-27 11:29:21 -0800564 return INVALID_OPERATION;
565 }
566
567 if (mCurrentFence->isValid()) {
568 if (SyncFeatures::getInstance().useWaitSync()) {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800569 base::unique_fd fenceFd(mCurrentFence->dup());
Chia-I Wuf1405182017-11-27 11:29:21 -0800570 if (fenceFd == -1) {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800571 BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno);
Chia-I Wuf1405182017-11-27 11:29:21 -0800572 return -errno;
573 }
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800574 if (!mRE.waitFence(std::move(fenceFd))) {
575 BLC_LOGE("doFenceWait: failed to wait on fence fd");
Chia-I Wuf1405182017-11-27 11:29:21 -0800576 return UNKNOWN_ERROR;
577 }
578 } else {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800579 status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doFenceWaitLocked");
Chia-I Wuf1405182017-11-27 11:29:21 -0800580 if (err != NO_ERROR) {
Chia-I Wu3498e3c2017-12-01 10:19:38 -0800581 BLC_LOGE("doFenceWait: error waiting for fence: %d", err);
Chia-I Wuf1405182017-11-27 11:29:21 -0800582 return err;
583 }
584 }
585 }
586
587 return NO_ERROR;
588}
589
590void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
591 BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
592 if (slotIndex == mCurrentTexture) {
593 mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
594 }
595 mEglSlots[slotIndex].mEglImage.clear();
596 ConsumerBase::freeBufferLocked(slotIndex);
597}
598
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800599void BufferLayerConsumer::onDisconnect() {
600 sp<Layer> l = mLayer.promote();
601 if (l.get()) {
602 l->onDisconnect();
603 }
604}
605
Chia-I Wufd257f82017-11-27 14:51:06 -0800606void BufferLayerConsumer::onSidebandStreamChanged() {
607 FrameAvailableListener* unsafeFrameAvailableListener = nullptr;
608 {
609 Mutex::Autolock lock(mFrameAvailableMutex);
610 unsafeFrameAvailableListener = mFrameAvailableListener.unsafe_get();
611 }
612 sp<ContentsChangedListener> listener;
613 { // scope for the lock
614 Mutex::Autolock lock(mMutex);
615 ALOG_ASSERT(unsafeFrameAvailableListener == mContentsChangedListener.unsafe_get());
616 listener = mContentsChangedListener.promote();
617 }
618
619 if (listener != NULL) {
620 listener->onSidebandStreamChanged();
621 }
622}
623
Chia-I Wuc75c44d2017-11-27 14:32:57 -0800624void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
625 FrameEventHistoryDelta* outDelta) {
626 sp<Layer> l = mLayer.promote();
627 if (l.get()) {
628 l->addAndGetFrameTimestamps(newTimestamps, outDelta);
629 }
630}
631
Chia-I Wuf1405182017-11-27 11:29:21 -0800632void BufferLayerConsumer::abandonLocked() {
633 BLC_LOGV("abandonLocked");
634 mCurrentTextureImage.clear();
635 ConsumerBase::abandonLocked();
636}
637
638status_t BufferLayerConsumer::setConsumerUsageBits(uint64_t usage) {
639 return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
640}
641
642void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const {
643 result.appendFormat("%smTexName=%d mCurrentTexture=%d\n"
644 "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
645 prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
646 mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
647 mCurrentTransform);
648
649 ConsumerBase::dumpLocked(result, prefix);
650}
651
652BufferLayerConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer)
653 : mGraphicBuffer(graphicBuffer),
654 mEglImage(EGL_NO_IMAGE_KHR),
655 mEglDisplay(EGL_NO_DISPLAY),
656 mCropRect(Rect::EMPTY_RECT) {}
657
658BufferLayerConsumer::EglImage::~EglImage() {
659 if (mEglImage != EGL_NO_IMAGE_KHR) {
660 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
661 ALOGE("~EglImage: eglDestroyImageKHR failed");
662 }
663 eglTerminate(mEglDisplay);
664 }
665}
666
Chia-I Wuc91077c2017-11-27 13:32:04 -0800667status_t BufferLayerConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
668 const Rect& cropRect) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800669 // If there's an image and it's no longer valid, destroy it.
670 bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
671 bool displayInvalid = mEglDisplay != eglDisplay;
672 bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
Chia-I Wuc91077c2017-11-27 13:32:04 -0800673 if (haveImage && (displayInvalid || cropInvalid)) {
Chia-I Wuf1405182017-11-27 11:29:21 -0800674 if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
675 ALOGE("createIfNeeded: eglDestroyImageKHR failed");
676 }
677 eglTerminate(mEglDisplay);
678 mEglImage = EGL_NO_IMAGE_KHR;
679 mEglDisplay = EGL_NO_DISPLAY;
680 }
681
682 // If there's no image, create one.
683 if (mEglImage == EGL_NO_IMAGE_KHR) {
684 mEglDisplay = eglDisplay;
685 mCropRect = cropRect;
686 mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect);
687 }
688
689 // Fail if we can't create a valid image.
690 if (mEglImage == EGL_NO_IMAGE_KHR) {
691 mEglDisplay = EGL_NO_DISPLAY;
692 mCropRect.makeInvalid();
693 const sp<GraphicBuffer>& buffer = mGraphicBuffer;
694 ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
695 buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
696 buffer->getPixelFormat());
697 return UNKNOWN_ERROR;
698 }
699
700 return OK;
701}
702
703void BufferLayerConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) {
704 glEGLImageTargetTexture2DOES(texTarget, static_cast<GLeglImageOES>(mEglImage));
705}
706
707EGLImageKHR BufferLayerConsumer::EglImage::createImage(EGLDisplay dpy,
708 const sp<GraphicBuffer>& graphicBuffer,
709 const Rect& crop) {
710 EGLClientBuffer cbuf = static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
711 const bool createProtectedImage =
712 (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) && hasEglProtectedContent();
713 EGLint attrs[] = {
714 EGL_IMAGE_PRESERVED_KHR,
715 EGL_TRUE,
716 EGL_IMAGE_CROP_LEFT_ANDROID,
717 crop.left,
718 EGL_IMAGE_CROP_TOP_ANDROID,
719 crop.top,
720 EGL_IMAGE_CROP_RIGHT_ANDROID,
721 crop.right,
722 EGL_IMAGE_CROP_BOTTOM_ANDROID,
723 crop.bottom,
724 createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
725 createProtectedImage ? EGL_TRUE : EGL_NONE,
726 EGL_NONE,
727 };
728 if (!crop.isValid()) {
729 // No crop rect to set, so leave the crop out of the attrib array. Make
730 // sure to propagate the protected content attrs if they are set.
731 attrs[2] = attrs[10];
732 attrs[3] = attrs[11];
733 attrs[4] = EGL_NONE;
734 } else if (!isEglImageCroppable(crop)) {
735 // The crop rect is not at the origin, so we can't set the crop on the
736 // EGLImage because that's not allowed by the EGL_ANDROID_image_crop
737 // extension. In the future we can add a layered extension that
738 // removes this restriction if there is hardware that can support it.
739 attrs[2] = attrs[10];
740 attrs[3] = attrs[11];
741 attrs[4] = EGL_NONE;
742 }
743 eglInitialize(dpy, 0, 0);
744 EGLImageKHR image =
745 eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
746 if (image == EGL_NO_IMAGE_KHR) {
747 EGLint error = eglGetError();
748 ALOGE("error creating EGLImage: %#x", error);
749 eglTerminate(dpy);
750 }
751 return image;
752}
753
754}; // namespace android