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 23using namespace android; 24 25BufferQueueScheduler::BufferQueueScheduler( 26 const sp<SurfaceControl>& surfaceControl, const HSV& color, int id) 27 : mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {} 28 29void 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 55void BufferQueueScheduler::addEvent(const BufferEvent& event) { 56 std::lock_guard<std::mutex> lock(mMutex); 57 mBufferEvents.push(event); 58 mCondition.notify_one(); 59} 60 61void BufferQueueScheduler::stopScheduling() { 62 std::lock_guard<std::mutex> lock(mMutex); 63 mContinueScheduling = false; 64 mCondition.notify_one(); 65} 66 67void 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 75void BufferQueueScheduler::bufferUpdate(const Dimensions& dimensions) { 76 sp<Surface> s = mSurfaceControl->getSurface(); 77 s->setBuffersDimensions(dimensions.width, dimensions.height); 78} 79 80void 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