blob: 77de8dc44c092196a4795e86dcf9a5912e6d0a44 [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(
Sahil Dhanju01041fe2016-08-08 20:27:23 -070026 const sp<SurfaceControl>& surfaceControl, const HSV& color, int id)
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -070027 : 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);
Sahil Dhanju01041fe2016-08-08 20:27:23 -070047 mColor.modulate();
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -070048 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(
Sahil Dhanju01041fe2016-08-08 20:27:23 -070068 const sp<SurfaceControl>& surfaceControl, const HSV& color) {
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -070069 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
Sahil Dhanju01041fe2016-08-08 20:27:23 -070080void BufferQueueScheduler::fillSurface(const std::shared_ptr<Event>& event) {
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -070081 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
Sahil Dhanju01041fe2016-08-08 20:27:23 -070091 auto color = mColor.getRGB();
92
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -070093 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));
Sahil Dhanju01041fe2016-08-08 20:27:23 -070097 pixel[0] = color.r;
98 pixel[1] = color.g;
99 pixel[2] = color.b;
Sahil Dhanjuc1ba5c42016-06-07 20:09:20 -0700100 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}