Home | History | Annotate | Download | only in src
      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