blob: 077a8f73b0da5dcfae802f23f06f6ea50cc4f589 [file] [log] [blame]
Stan Iliev564ca3e2018-09-04 22:00:00 +00001/*
2 * Copyright (C) 2018 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#include "ImageConsumer.h"
18#include <gui/BufferQueue.h>
19#include "Properties.h"
20#include "SurfaceTexture.h"
21#include "renderstate/RenderState.h"
22#include "renderthread/EglManager.h"
23#include "renderthread/RenderThread.h"
24#include "renderthread/VulkanManager.h"
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040025#include "utils/Color.h"
Stan Iliev902ce2a2019-03-07 18:13:55 -050026#include <GrAHardwareBufferUtils.h>
Stan Iliev564ca3e2018-09-04 22:00:00 +000027
28// Macro for including the SurfaceTexture name in log messages
29#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
30
31namespace android {
32
33void ImageConsumer::onFreeBufferLocked(int slotIndex) {
Stan Iliev902ce2a2019-03-07 18:13:55 -050034 mImageSlots[slotIndex].clear();
Stan Iliev564ca3e2018-09-04 22:00:00 +000035}
36
37void ImageConsumer::onAcquireBufferLocked(BufferItem* item) {
38 // If item->mGraphicBuffer is not null, this buffer has not been acquired
39 // before, so any prior SkImage is created with a stale buffer. This resets the stale SkImage.
40 if (item->mGraphicBuffer != nullptr) {
Stan Iliev902ce2a2019-03-07 18:13:55 -050041 mImageSlots[item->mSlot].clear();
Stan Iliev564ca3e2018-09-04 22:00:00 +000042 }
43}
44
45void ImageConsumer::onReleaseBufferLocked(int buf) {
Stan Iliev902ce2a2019-03-07 18:13:55 -050046 mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR;
Stan Iliev564ca3e2018-09-04 22:00:00 +000047}
48
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040049void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer,
Stan Iliev902ce2a2019-03-07 18:13:55 -050050 android_dataspace dataspace, bool forceCreate,
51 GrContext* context) {
Stan Iliev26679ce2019-01-30 14:04:53 -050052 if (!mImage.get() || dataspace != mDataspace || forceCreate) {
Stan Iliev902ce2a2019-03-07 18:13:55 -050053 if (!graphicBuffer.get()) {
54 clear();
55 return;
56 }
57
58 if (!mBackendTexture.isValid()) {
59 clear();
60 bool createProtectedImage =
61 0 != (graphicBuffer->getUsage() & GraphicBuffer::USAGE_PROTECTED);
62 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(
63 context,
64 reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
65 graphicBuffer->getPixelFormat(),
66 false);
67 mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture(
68 context,
69 reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
70 graphicBuffer->getWidth(),
71 graphicBuffer->getHeight(),
72 &mDeleteProc,
73 &mDeleteCtx,
74 createProtectedImage,
75 backendFormat,
76 false);
77 }
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040078 mDataspace = dataspace;
Stan Iliev902ce2a2019-03-07 18:13:55 -050079 SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(
80 graphicBuffer->getPixelFormat());
81 mImage = SkImage::MakeFromTexture(context,
82 mBackendTexture,
83 kTopLeft_GrSurfaceOrigin,
84 colorType,
85 kPremul_SkAlphaType,
86 uirenderer::DataSpaceToColorSpace(dataspace));
87 }
88}
89
90void ImageConsumer::ImageSlot::clear() {
91 mImage.reset();
92 if (mBackendTexture.isValid()) {
93 mDeleteProc(mDeleteCtx);
94 mBackendTexture = {};
Stan Iliev564ca3e2018-09-04 22:00:00 +000095 }
96}
97
98sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
99 uirenderer::RenderState& renderState) {
100 BufferItem item;
101 status_t err;
102 err = st.acquireBufferLocked(&item, 0);
103 if (err != OK) {
104 if (err != BufferQueue::NO_BUFFER_AVAILABLE) {
105 IMG_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
106 } else {
107 int slot = st.mCurrentTexture;
108 if (slot != BufferItem::INVALID_BUFFER_SLOT) {
109 *queueEmpty = true;
Stan Ilievf6a4ee52018-12-17 17:37:38 -0500110 mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer,
Stan Iliev902ce2a2019-03-07 18:13:55 -0500111 st.mCurrentDataSpace, false, renderState.getRenderThread().getGrContext());
112 return mImageSlots[slot].getImage();
Stan Iliev564ca3e2018-09-04 22:00:00 +0000113 }
114 }
115 return nullptr;
116 }
117
118 int slot = item.mSlot;
119 if (item.mFence->isValid()) {
120 // Wait on the producer fence for the buffer to be ready.
121 if (uirenderer::Properties::getRenderPipelineType() ==
122 uirenderer::RenderPipelineType::SkiaGL) {
123 err = renderState.getRenderThread().eglManager().fenceWait(item.mFence);
124 } else {
125 err = renderState.getRenderThread().vulkanManager().fenceWait(item.mFence);
126 }
127 if (err != OK) {
128 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
129 EGL_NO_SYNC_KHR);
130 return nullptr;
131 }
132 }
133
134 // Release old buffer.
135 if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) {
136 // If needed, set the released slot's fence to guard against a producer accessing the
137 // buffer before the outstanding accesses have completed.
138 sp<Fence> releaseFence;
139 EGLDisplay display = EGL_NO_DISPLAY;
140 if (uirenderer::Properties::getRenderPipelineType() ==
141 uirenderer::RenderPipelineType::SkiaGL) {
142 auto& eglManager = renderState.getRenderThread().eglManager();
143 display = eglManager.eglDisplay();
Stan Iliev902ce2a2019-03-07 18:13:55 -0500144 err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].eglFence(),
Stan Iliev564ca3e2018-09-04 22:00:00 +0000145 releaseFence);
146 } else {
147 err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence);
148 }
149 if (OK != err) {
150 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
151 EGL_NO_SYNC_KHR);
152 return nullptr;
153 }
154
155 if (releaseFence.get()) {
156 status_t err = st.addReleaseFenceLocked(
157 st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, releaseFence);
158 if (err != OK) {
159 IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
160 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
161 EGL_NO_SYNC_KHR);
162 return nullptr;
163 }
164 }
165
166 // Finally release the old buffer.
167 status_t status = st.releaseBufferLocked(
168 st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
Stan Iliev902ce2a2019-03-07 18:13:55 -0500169 mImageSlots[st.mCurrentTexture].eglFence());
Stan Iliev564ca3e2018-09-04 22:00:00 +0000170 if (status < NO_ERROR) {
171 IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
172 err = status;
173 // Keep going, with error raised.
174 }
175 }
176
177 // Update the state.
178 st.mCurrentTexture = slot;
179 st.mCurrentCrop = item.mCrop;
180 st.mCurrentTransform = item.mTransform;
181 st.mCurrentScalingMode = item.mScalingMode;
182 st.mCurrentTimestamp = item.mTimestamp;
183 st.mCurrentDataSpace = item.mDataSpace;
184 st.mCurrentFence = item.mFence;
185 st.mCurrentFenceTime = item.mFenceTime;
186 st.mCurrentFrameNumber = item.mFrameNumber;
187 st.computeCurrentTransformMatrixLocked();
188
189 *queueEmpty = false;
Stan Iliev902ce2a2019-03-07 18:13:55 -0500190 mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace, true,
191 renderState.getRenderThread().getGrContext());
192 return mImageSlots[slot].getImage();
Stan Iliev564ca3e2018-09-04 22:00:00 +0000193}
194
195} /* namespace android */