1 /* 2 * Copyright 2019 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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19 #include <android-base/stringprintf.h> 20 #include <android/native_window.h> 21 #include <compositionengine/CompositionEngine.h> 22 #include <compositionengine/Display.h> 23 #include <compositionengine/DisplaySurface.h> 24 #include <compositionengine/RenderSurfaceCreationArgs.h> 25 #include <compositionengine/impl/DumpHelpers.h> 26 #include <compositionengine/impl/RenderSurface.h> 27 #include <log/log.h> 28 #include <renderengine/RenderEngine.h> 29 #include <sync/sync.h> 30 #include <system/window.h> 31 #include <ui/GraphicBuffer.h> 32 #include <ui/Rect.h> 33 #include <utils/Trace.h> 34 35 #include "DisplayHardware/HWComposer.h" 36 37 namespace android::compositionengine { 38 39 RenderSurface::~RenderSurface() = default; 40 41 namespace impl { 42 43 std::unique_ptr<compositionengine::RenderSurface> createRenderSurface( 44 const compositionengine::CompositionEngine& compositionEngine, 45 compositionengine::Display& display, compositionengine::RenderSurfaceCreationArgs&& args) { 46 return std::make_unique<RenderSurface>(compositionEngine, display, std::move(args)); 47 } 48 49 RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display& display, 50 RenderSurfaceCreationArgs&& args) 51 : mCompositionEngine(compositionEngine), 52 mDisplay(display), 53 mNativeWindow(args.nativeWindow), 54 mDisplaySurface(args.displaySurface), 55 mSize(args.displayWidth, args.displayHeight) { 56 LOG_ALWAYS_FATAL_IF(!mNativeWindow); 57 } 58 59 RenderSurface::~RenderSurface() { 60 ANativeWindow* const window = mNativeWindow.get(); 61 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 62 } 63 64 bool RenderSurface::isValid() const { 65 return mSize.isValid(); 66 } 67 68 void RenderSurface::initialize() { 69 ANativeWindow* const window = mNativeWindow.get(); 70 71 int status = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); 72 ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status); 73 status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); 74 ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status); 75 status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER); 76 ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status); 77 } 78 79 const ui::Size& RenderSurface::getSize() const { 80 return mSize; 81 } 82 83 const sp<Fence>& RenderSurface::getClientTargetAcquireFence() const { 84 return mDisplaySurface->getClientTargetAcquireFence(); 85 } 86 87 void RenderSurface::setDisplaySize(const ui::Size& size) { 88 mDisplaySurface->resizeBuffers(size.width, size.height); 89 mSize = size; 90 } 91 92 void RenderSurface::setBufferDataspace(ui::Dataspace dataspace) { 93 native_window_set_buffers_data_space(mNativeWindow.get(), 94 static_cast<android_dataspace>(dataspace)); 95 } 96 97 void RenderSurface::setProtected(bool useProtected) { 98 uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER; 99 if (useProtected) { 100 usageFlags |= GRALLOC_USAGE_PROTECTED; 101 } 102 const int status = native_window_set_usage(mNativeWindow.get(), usageFlags); 103 ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status); 104 if (status == NO_ERROR) { 105 mProtected = useProtected; 106 } 107 } 108 109 status_t RenderSurface::beginFrame(bool mustRecompose) { 110 return mDisplaySurface->beginFrame(mustRecompose); 111 } 112 113 status_t RenderSurface::prepareFrame() { 114 auto& hwc = mCompositionEngine.getHwComposer(); 115 const auto id = mDisplay.getId(); 116 if (id) { 117 status_t error = hwc.prepare(*id, mDisplay); 118 if (error != NO_ERROR) { 119 return error; 120 } 121 } 122 123 DisplaySurface::CompositionType compositionType; 124 const bool hasClient = hwc.hasClientComposition(id); 125 const bool hasDevice = hwc.hasDeviceComposition(id); 126 if (hasClient && hasDevice) { 127 compositionType = DisplaySurface::COMPOSITION_MIXED; 128 } else if (hasClient) { 129 compositionType = DisplaySurface::COMPOSITION_GLES; 130 } else if (hasDevice) { 131 compositionType = DisplaySurface::COMPOSITION_HWC; 132 } else { 133 // Nothing to do -- when turning the screen off we get a frame like 134 // this. Call it a HWC frame since we won't be doing any GLES work but 135 // will do a prepare/set cycle. 136 compositionType = DisplaySurface::COMPOSITION_HWC; 137 } 138 return mDisplaySurface->prepareFrame(compositionType); 139 } 140 141 sp<GraphicBuffer> RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { 142 ATRACE_CALL(); 143 int fd = -1; 144 ANativeWindowBuffer* buffer = nullptr; 145 146 status_t result = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fd); 147 148 if (result != NO_ERROR) { 149 ALOGE("ANativeWindow::dequeueBuffer failed for display [%s] with error: %d", 150 mDisplay.getName().c_str(), result); 151 // Return fast here as we can't do much more - any rendering we do 152 // now will just be wrong. 153 return mGraphicBuffer; 154 } 155 156 ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", 157 mGraphicBuffer->getNativeBuffer()->handle); 158 mGraphicBuffer = GraphicBuffer::from(buffer); 159 160 *bufferFence = base::unique_fd(fd); 161 162 return mGraphicBuffer; 163 } 164 165 void RenderSurface::queueBuffer(base::unique_fd&& readyFence) { 166 auto& hwc = mCompositionEngine.getHwComposer(); 167 const auto id = mDisplay.getId(); 168 169 if (hwc.hasClientComposition(id) || hwc.hasFlipClientTargetRequest(id)) { 170 // hasFlipClientTargetRequest could return true even if we haven't 171 // dequeued a buffer before. Try dequeueing one if we don't have a 172 // buffer ready. 173 if (mGraphicBuffer == nullptr) { 174 ALOGI("Attempting to queue a client composited buffer without one " 175 "previously dequeued for display [%s]. Attempting to dequeue " 176 "a scratch buffer now", 177 mDisplay.getName().c_str()); 178 // We shouldn't deadlock here, since mGraphicBuffer == nullptr only 179 // after a successful call to queueBuffer, or if dequeueBuffer has 180 // never been called. 181 base::unique_fd unused; 182 dequeueBuffer(&unused); 183 } 184 185 if (mGraphicBuffer == nullptr) { 186 ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); 187 } else { 188 status_t result = 189 mNativeWindow->queueBuffer(mNativeWindow.get(), 190 mGraphicBuffer->getNativeBuffer(), dup(readyFence)); 191 if (result != NO_ERROR) { 192 ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), 193 result); 194 // We risk blocking on dequeueBuffer if the primary display failed 195 // to queue up its buffer, so crash here. 196 if (!mDisplay.isVirtual()) { 197 LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); 198 } else { 199 mNativeWindow->cancelBuffer(mNativeWindow.get(), 200 mGraphicBuffer->getNativeBuffer(), dup(readyFence)); 201 } 202 } 203 204 mGraphicBuffer = nullptr; 205 } 206 } 207 208 status_t result = mDisplaySurface->advanceFrame(); 209 if (result != NO_ERROR) { 210 ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplay.getName().c_str(), result); 211 } 212 } 213 214 void RenderSurface::onPresentDisplayCompleted() { 215 mDisplaySurface->onFrameCommitted(); 216 } 217 218 void RenderSurface::setViewportAndProjection() { 219 auto& renderEngine = mCompositionEngine.getRenderEngine(); 220 Rect sourceCrop = Rect(mSize); 221 renderEngine.setViewportAndProjection(mSize.width, mSize.height, sourceCrop, 222 ui::Transform::ROT_0); 223 } 224 225 void RenderSurface::flip() { 226 mPageFlipCount++; 227 } 228 229 void RenderSurface::dump(std::string& out) const { 230 using android::base::StringAppendF; 231 232 out.append(" Composition RenderSurface State:"); 233 234 out.append("\n "); 235 236 dumpVal(out, "size", mSize); 237 StringAppendF(&out, "ANativeWindow=%p (format %d) ", mNativeWindow.get(), 238 ANativeWindow_getFormat(mNativeWindow.get())); 239 dumpVal(out, "flips", mPageFlipCount); 240 out.append("\n"); 241 242 String8 surfaceDump; 243 mDisplaySurface->dumpAsString(surfaceDump); 244 out.append(surfaceDump); 245 } 246 247 std::uint32_t RenderSurface::getPageFlipCount() const { 248 return mPageFlipCount; 249 } 250 251 void RenderSurface::setPageFlipCountForTest(std::uint32_t count) { 252 mPageFlipCount = count; 253 } 254 255 void RenderSurface::setSizeForTest(const ui::Size& size) { 256 mSize = size; 257 } 258 259 sp<GraphicBuffer>& RenderSurface::mutableGraphicBufferForTest() { 260 return mGraphicBuffer; 261 } 262 263 } // namespace impl 264 } // namespace android::compositionengine 265