blob: 15aec9f291a4e5ade22cf3d6f99f559db378f3ac [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;
Derek Sollenbergerd01b5912018-10-19 15:55:33 -040073 mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
Stan Iliev564ca3e2018-09-04 22:00:00 +000074 return mImageSlots[slot].mImage;
75 }
76 }
77 return nullptr;
78 }
79
80 int slot = item.mSlot;
81 if (item.mFence->isValid()) {
82 // Wait on the producer fence for the buffer to be ready.
83 if (uirenderer::Properties::getRenderPipelineType() ==
84 uirenderer::RenderPipelineType::SkiaGL) {
85 err = renderState.getRenderThread().eglManager().fenceWait(item.mFence);
86 } else {
87 err = renderState.getRenderThread().vulkanManager().fenceWait(item.mFence);
88 }
89 if (err != OK) {
90 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
91 EGL_NO_SYNC_KHR);
92 return nullptr;
93 }
94 }
95
96 // Release old buffer.
97 if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) {
98 // If needed, set the released slot's fence to guard against a producer accessing the
99 // buffer before the outstanding accesses have completed.
100 sp<Fence> releaseFence;
101 EGLDisplay display = EGL_NO_DISPLAY;
102 if (uirenderer::Properties::getRenderPipelineType() ==
103 uirenderer::RenderPipelineType::SkiaGL) {
104 auto& eglManager = renderState.getRenderThread().eglManager();
105 display = eglManager.eglDisplay();
106 err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].mEglFence,
107 releaseFence);
108 } else {
109 err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence);
110 }
111 if (OK != err) {
112 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
113 EGL_NO_SYNC_KHR);
114 return nullptr;
115 }
116
117 if (releaseFence.get()) {
118 status_t err = st.addReleaseFenceLocked(
119 st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, releaseFence);
120 if (err != OK) {
121 IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err);
122 st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY,
123 EGL_NO_SYNC_KHR);
124 return nullptr;
125 }
126 }
127
128 // Finally release the old buffer.
129 status_t status = st.releaseBufferLocked(
130 st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
131 mImageSlots[st.mCurrentTexture].mEglFence);
132 if (status < NO_ERROR) {
133 IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
134 err = status;
135 // Keep going, with error raised.
136 }
137 }
138
139 // Update the state.
140 st.mCurrentTexture = slot;
141 st.mCurrentCrop = item.mCrop;
142 st.mCurrentTransform = item.mTransform;
143 st.mCurrentScalingMode = item.mScalingMode;
144 st.mCurrentTimestamp = item.mTimestamp;
145 st.mCurrentDataSpace = item.mDataSpace;
146 st.mCurrentFence = item.mFence;
147 st.mCurrentFenceTime = item.mFenceTime;
148 st.mCurrentFrameNumber = item.mFrameNumber;
149 st.computeCurrentTransformMatrixLocked();
150
151 *queueEmpty = false;
Derek Sollenbergerd01b5912018-10-19 15:55:33 -0400152 mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
Stan Iliev564ca3e2018-09-04 22:00:00 +0000153 return mImageSlots[slot].mImage;
154}
155
156} /* namespace android */