You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.3 KiB
110 lines
3.3 KiB
4 months ago
|
/*
|
||
|
* Copyright 2016 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
#define LOG_TAG "BufferQueueScheduler"
|
||
|
|
||
|
#include "BufferQueueScheduler.h"
|
||
|
|
||
|
#include <android/native_window.h>
|
||
|
#include <gui/Surface.h>
|
||
|
|
||
|
using namespace android;
|
||
|
|
||
|
BufferQueueScheduler::BufferQueueScheduler(
|
||
|
const sp<SurfaceControl>& surfaceControl, const HSV& color, int id)
|
||
|
: mSurfaceControl(surfaceControl), mColor(color), mSurfaceId(id), mContinueScheduling(true) {}
|
||
|
|
||
|
void BufferQueueScheduler::startScheduling() {
|
||
|
ALOGV("Starting Scheduler for %d Layer", mSurfaceId);
|
||
|
std::unique_lock<std::mutex> lock(mMutex);
|
||
|
if (mSurfaceControl == nullptr) {
|
||
|
mCondition.wait(lock, [&] { return (mSurfaceControl != nullptr); });
|
||
|
}
|
||
|
|
||
|
while (mContinueScheduling) {
|
||
|
while (true) {
|
||
|
if (mBufferEvents.empty()) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
BufferEvent event = mBufferEvents.front();
|
||
|
lock.unlock();
|
||
|
|
||
|
bufferUpdate(event.dimensions);
|
||
|
fillSurface(event.event);
|
||
|
mColor.modulate();
|
||
|
lock.lock();
|
||
|
mBufferEvents.pop();
|
||
|
}
|
||
|
mCondition.wait(lock);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void BufferQueueScheduler::addEvent(const BufferEvent& event) {
|
||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||
|
mBufferEvents.push(event);
|
||
|
mCondition.notify_one();
|
||
|
}
|
||
|
|
||
|
void BufferQueueScheduler::stopScheduling() {
|
||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||
|
mContinueScheduling = false;
|
||
|
mCondition.notify_one();
|
||
|
}
|
||
|
|
||
|
void BufferQueueScheduler::setSurfaceControl(
|
||
|
const sp<SurfaceControl>& surfaceControl, const HSV& color) {
|
||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||
|
mSurfaceControl = surfaceControl;
|
||
|
mColor = color;
|
||
|
mCondition.notify_one();
|
||
|
}
|
||
|
|
||
|
void BufferQueueScheduler::bufferUpdate(const Dimensions& dimensions) {
|
||
|
sp<Surface> s = mSurfaceControl->getSurface();
|
||
|
s->setBuffersDimensions(dimensions.width, dimensions.height);
|
||
|
}
|
||
|
|
||
|
void BufferQueueScheduler::fillSurface(const std::shared_ptr<Event>& event) {
|
||
|
ANativeWindow_Buffer outBuffer;
|
||
|
sp<Surface> s = mSurfaceControl->getSurface();
|
||
|
|
||
|
status_t status = s->lock(&outBuffer, nullptr);
|
||
|
|
||
|
if (status != NO_ERROR) {
|
||
|
ALOGE("fillSurface: failed to lock buffer, (%d)", status);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
auto color = mColor.getRGB();
|
||
|
|
||
|
auto img = reinterpret_cast<uint8_t*>(outBuffer.bits);
|
||
|
for (int y = 0; y < outBuffer.height; y++) {
|
||
|
for (int x = 0; x < outBuffer.width; x++) {
|
||
|
uint8_t* pixel = img + (4 * (y * outBuffer.stride + x));
|
||
|
pixel[0] = color.r;
|
||
|
pixel[1] = color.g;
|
||
|
pixel[2] = color.b;
|
||
|
pixel[3] = LAYER_ALPHA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
event->readyToExecute();
|
||
|
|
||
|
status = s->unlockAndPost();
|
||
|
|
||
|
ALOGE_IF(status != NO_ERROR, "fillSurface: failed to unlock and post buffer, (%d)", status);
|
||
|
}
|