blob: cad11a0f873065c7bd39c9ece2211b07768ebe75 [file] [log] [blame]
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -07001/*
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 RGB& 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 lock.lock();
48 mBufferEvents.pop();
49 }
50 mCondition.wait(lock);
51 }
52}
53
54void BufferQueueScheduler::addEvent(const BufferEvent& event) {
55 std::lock_guard<std::mutex> lock(mMutex);
56 mBufferEvents.push(event);
57 mCondition.notify_one();
58}
59
60void BufferQueueScheduler::stopScheduling() {
61 std::lock_guard<std::mutex> lock(mMutex);
62 mContinueScheduling = false;
63 mCondition.notify_one();
64}
65
66void BufferQueueScheduler::setSurfaceControl(
67 const sp<SurfaceControl>& surfaceControl, const RGB& color) {
68 std::lock_guard<std::mutex> lock(mMutex);
69 mSurfaceControl = surfaceControl;
70 mColor = color;
71 mCondition.notify_one();
72}
73
74void BufferQueueScheduler::bufferUpdate(const Dimensions& dimensions) {
75 sp<Surface> s = mSurfaceControl->getSurface();
76 s->setBuffersDimensions(dimensions.width, dimensions.height);
77}
78
79void BufferQueueScheduler::fillSurface(std::shared_ptr<Event> event) {
80 ANativeWindow_Buffer outBuffer;
81 sp<Surface> s = mSurfaceControl->getSurface();
82
83 status_t status = s->lock(&outBuffer, nullptr);
84
85 if (status != NO_ERROR) {
86 ALOGE("fillSurface: failed to lock buffer, (%d)", status);
87 return;
88 }
89
90 auto img = reinterpret_cast<uint8_t*>(outBuffer.bits);
91 for (int y = 0; y < outBuffer.height; y++) {
92 for (int x = 0; x < outBuffer.width; x++) {
93 uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
94 pixel[0] = mColor.r;
95 pixel[1] = mColor.g;
96 pixel[2] = mColor.b;
97 pixel[3] = LAYER_ALPHA;
98 }
99 }
100
101 event->readyToExecute();
102
103 status = s->unlockAndPost();
104
105 ALOGE_IF(status != NO_ERROR, "fillSurface: failed to unlock and post buffer, (%d)", status);
106}