blob: 4a2f57e344c4c9a4a59c75d310d9726e0dd9ab78 [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 Iliev564ca3e2018-09-04 22:00:00 +000026
27// Macro for including the SurfaceTexture name in log messages
28#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
29
30namespace android {
31
32void ImageConsumer::onFreeBufferLocked(int slotIndex) {
33 mImageSlots[slotIndex].mImage.reset();
34}
35
36void ImageConsumer::onAcquireBufferLocked(BufferItem* item) {
37 // If item->mGraphicBuffer is not null, this buffer has not been acquired
38 // before, so any prior SkImage is created with a stale buffer. This resets the stale SkImage.
39 if (item->mGraphicBuffer != nullptr) {
40 mImageSlots[item->mSlot].mImage.reset();
41 }
42}
43
44void ImageConsumer::onReleaseBufferLocked(int buf) {
45 mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
46}
47
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040048void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer,
49 android_dataspace dataspace) {
50 if (!mImage.get() || dataspace != mDataspace) {
Stan Iliev564ca3e2018-09-04 22:00:00 +000051 mImage = graphicBuffer.get()
52 ? SkImage::MakeFromAHardwareBuffer(
53 reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040054 kPremul_SkAlphaType,
55 uirenderer::DataSpaceToColorSpace(dataspace))
Stan Iliev564ca3e2018-09-04 22:00:00 +000056 : nullptr;
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040057 mDataspace = dataspace;
Stan Iliev564ca3e2018-09-04 22:00:00 +000058 }
59}
60
61sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
62 uirenderer::RenderState& renderState) {
63 BufferItem item;
64 status_t err;
65 err = st.acquireBufferLocked(&item, 0);
66 if (err != OK) {
67 if (err != BufferQueue::NO_BUFFER_AVAILABLE) {
68 IMG_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err);
69 } else {
70 int slot = st.mCurrentTexture;
71 if (slot != BufferItem::INVALID_BUFFER_SLOT) {
72 *queueEmpty = true;
Stan Ilievf6a4ee52018-12-17 17:37:38 -050073 mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer,
74 st.mCurrentDataSpace);
Stan Iliev564ca3e2018-09-04 22:00:00 +000075 return mImageSlots[slot].mImage;
76 }
77 }
78 return nullptr;
79 }
80
81 int slot = item.mSlot;
82 if (item.mFence->isValid()) {
83 // Wait on the producer fence for the buffer to be ready.
84 if (uirenderer::Properties::getRenderPipelineType() ==
85 uirenderer::RenderPipelineType::SkiaGL) {
86 err = renderState.getRenderThread().eglManager().fenceWait(item.mFence);
87 } else {
88 err = renderState.getRenderThread().vulkanManager().fenceWait(item.mFence);
89 }
90 if (err != OK) {
91 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
92 EGL_NO_SYNC_KHR);
93 return nullptr;
94 }
95 }
96
97 // Release old buffer.
98 if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) {
99 // If needed, set the released slot's fence to guard against a producer accessing the
100 // buffer before the outstanding accesses have completed.
101 sp<Fence> releaseFence;
102 EGLDisplay display = EGL_NO_DISPLAY;
103 if (uirenderer::Properties::getRenderPipelineType() ==
104 uirenderer::RenderPipelineType::SkiaGL) {
105 auto& eglManager = renderState.getRenderThread().eglManager();
106 display = eglManager.eglDisplay();
107 err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].mEglFence,
108 releaseFence);
109 } else {
110 err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence);
111 }
112 if (OK != err) {
113 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
114 EGL_NO_SYNC_KHR);
115 return nullptr;
116 }
117
118 if (releaseFence.get()) {
119 status_t err = st.addReleaseFenceLocked(
120 st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, releaseFence);
121 if (err != OK) {
122 IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
123 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
124 EGL_NO_SYNC_KHR);
125 return nullptr;
126 }
127 }
128
129 // Finally release the old buffer.
130 status_t status = st.releaseBufferLocked(
131 st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
132 mImageSlots[st.mCurrentTexture].mEglFence);
133 if (status < NO_ERROR) {
134 IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
135 err = status;
136 // Keep going, with error raised.
137 }
138 }
139
140 // Update the state.
141 st.mCurrentTexture = slot;
142 st.mCurrentCrop = item.mCrop;
143 st.mCurrentTransform = item.mTransform;
144 st.mCurrentScalingMode = item.mScalingMode;
145 st.mCurrentTimestamp = item.mTimestamp;
146 st.mCurrentDataSpace = item.mDataSpace;
147 st.mCurrentFence = item.mFence;
148 st.mCurrentFenceTime = item.mFenceTime;
149 st.mCurrentFrameNumber = item.mFrameNumber;
150 st.computeCurrentTransformMatrixLocked();
151
152 *queueEmpty = false;
Derek Sollenbergerd01b5912018-10-19 15:55:33 -0400153 mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
Stan Iliev564ca3e2018-09-04 22:00:00 +0000154 return mImageSlots[slot].mImage;
155}
156
157} /* namespace android */