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
BufferQueueScheduler(const sp<SurfaceControl> & surfaceControl,const HSV & color,int id)25 BufferQueueScheduler::BufferQueueScheduler(
26 const sp<SurfaceControl>& surfaceControl, const HSV& color, int id)
27 : mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {}
28
startScheduling()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
addEvent(const BufferEvent & event)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
stopScheduling()61 void BufferQueueScheduler::stopScheduling() {
62 std::lock_guard<std::mutex> lock(mMutex);
63 mContinueScheduling = false;
64 mCondition.notify_one();
65 }
66
setSurfaceControl(const sp<SurfaceControl> & surfaceControl,const HSV & color)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
bufferUpdate(const Dimensions & dimensions)75 void BufferQueueScheduler::bufferUpdate(const Dimensions& dimensions) {
76 sp<Surface> s = mSurfaceControl->getSurface();
77 s->setBuffersDimensions(dimensions.width, dimensions.height);
78 }
79
fillSurface(const std::shared_ptr<Event> & event)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