Home | History | Annotate | Download | only in replayer
      1 /*
      2  * Copyright 2016 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 #define LOG_TAG "BufferQueueScheduler"
     17 
     18 #include "BufferQueueScheduler.h"
     19 
     20 #include <android/native_window.h>
     21 #include <gui/Surface.h>
     22 
     23 using namespace android;
     24 
     25 BufferQueueScheduler::BufferQueueScheduler(
     26         const sp<SurfaceControl>& surfaceControl, const HSV& color, int id)
     27       : mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {}
     28 
     29 void BufferQueueScheduler::startScheduling() {
     30     ALOGV("Starting Scheduler for %d Layer", mSurfaceId);
     31     std::unique_lock<std::mutex> lock(mMutex);
     32     if (mSurfaceControl == nullptr) {
     33         mCondition.wait(lock, [&] { return (mSurfaceControl != nullptr); });
     34     }
     35 
     36     while (mContinueScheduling) {
     37         while (true) {
     38             if (mBufferEvents.empty()) {
     39                 break;
     40             }
     41 
     42             BufferEvent event = mBufferEvents.front();
     43             lock.unlock();
     44 
     45             bufferUpdate(event.dimensions);
     46             fillSurface(event.event);
     47             mColor.modulate();
     48             lock.lock();
     49             mBufferEvents.pop();
     50         }
     51         mCondition.wait(lock);
     52     }
     53 }
     54 
     55 void BufferQueueScheduler::addEvent(const BufferEvent& event) {
     56     std::lock_guard<std::mutex> lock(mMutex);
     57     mBufferEvents.push(event);
     58     mCondition.notify_one();
     59 }
     60 
     61 void BufferQueueScheduler::stopScheduling() {
     62     std::lock_guard<std::mutex> lock(mMutex);
     63     mContinueScheduling = false;
     64     mCondition.notify_one();
     65 }
     66 
     67 void BufferQueueScheduler::setSurfaceControl(
     68         const sp<SurfaceControl>& surfaceControl, const HSV& color) {
     69     std::lock_guard<std::mutex> lock(mMutex);
     70     mSurfaceControl = surfaceControl;
     71     mColor = color;
     72     mCondition.notify_one();
     73 }
     74 
     75 void BufferQueueScheduler::bufferUpdate(const Dimensions& dimensions) {
     76     sp<Surface> s = mSurfaceControl->getSurface();
     77     s->setBuffersDimensions(dimensions.width, dimensions.height);
     78 }
     79 
     80 void BufferQueueScheduler::fillSurface(const std::shared_ptr<Event>& event) {
     81     ANativeWindow_Buffer outBuffer;
     82     sp<Surface> s = mSurfaceControl->getSurface();
     83 
     84     status_t status = s->lock(&outBuffer, nullptr);
     85 
     86     if (status != NO_ERROR) {
     87         ALOGE("fillSurface: failed to lock buffer, (%d)", status);
     88         return;
     89     }
     90 
     91     auto color = mColor.getRGB();
     92 
     93     auto img = reinterpret_cast<uint8_t*>(outBuffer.bits);
     94     for (int y = 0; y < outBuffer.height; y++) {
     95         for (int x = 0; x < outBuffer.width; x++) {
     96             uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
     97             pixel[0] = color.r;
     98             pixel[1] = color.g;
     99             pixel[2] = color.b;
    100             pixel[3] = LAYER_ALPHA;
    101         }
    102     }
    103 
    104     event->readyToExecute();
    105 
    106     status = s->unlockAndPost();
    107 
    108     ALOGE_IF(status != NO_ERROR, "fillSurface: failed to unlock and post buffer, (%d)", status);
    109 }
    110