blob: 88c7f52410eeef5a4059eb524abb7f29a89d81a2 [file] [log] [blame]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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.
#include "starboard/raspi/shared/dispmanx_util.h"
#include "starboard/common/scoped_ptr.h"
#include "starboard/memory.h"
namespace starboard {
namespace raspi {
namespace shared {
namespace {
class DispmanxAutoUpdate {
public:
DispmanxAutoUpdate() {
handle_ = vc_dispmanx_update_start(0 /*screen*/);
SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
}
~DispmanxAutoUpdate() {
if (handle_ != DISPMANX_NO_HANDLE) {
Update();
}
}
DISPMANX_UPDATE_HANDLE_T handle() const { return handle_; }
void Update() {
SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
int32_t result = vc_dispmanx_update_submit_sync(handle_);
SB_DCHECK(result == 0) << " result=" << result;
handle_ = DISPMANX_NO_HANDLE;
}
private:
DISPMANX_UPDATE_HANDLE_T handle_;
SB_DISALLOW_COPY_AND_ASSIGN(DispmanxAutoUpdate);
};
} // namespace
void DispmanxYUV420Resource::ClearWithBlack() {
scoped_array<uint8_t> data(new uint8_t[width_ * height_ * 3 / 2]);
SbMemorySet(data.get(), width_ * height_, 0);
SbMemorySet(data.get() + width_ * height_, width_ * height_ / 2, 0x80);
WriteData(data.get());
}
DispmanxElement::DispmanxElement(const DispmanxDisplay& display,
int32_t layer,
const DispmanxRect& dest_rect,
const DispmanxResource& src,
const DispmanxRect& src_rect) {
DispmanxAutoUpdate update;
handle_ = vc_dispmanx_element_add(update.handle(), display.handle(), layer,
&dest_rect, src.handle(), &src_rect,
DISPMANX_PROTECTION_NONE, NULL /*alpha*/,
NULL /*clamp*/, DISPMANX_NO_ROTATE);
SB_DCHECK(handle_ != DISPMANX_NO_HANDLE);
}
DispmanxElement::~DispmanxElement() {
DispmanxAutoUpdate update;
int32_t result = vc_dispmanx_element_remove(update.handle(), handle_);
SB_DCHECK(result == 0) << " result=" << result;
}
void DispmanxVideoRenderer::Update(const VideoFrame& video_frame) {
if (video_frame.IsEndOfStream()) {
element_.reset();
resource_.reset();
return;
}
if (!resource_ || resource_->width() != video_frame.width() ||
resource_->height() != video_frame.height()) {
element_.reset();
resource_.reset();
DispmanxRect src_rect(0, 0, video_frame.width() << 16,
video_frame.height() << 16);
resource_.reset(
new DispmanxYUV420Resource(video_frame.width(), video_frame.height()));
element_.reset(new DispmanxElement(display_, layer_, DispmanxRect(),
*resource_, src_rect));
}
resource_->WriteData(video_frame.GetPlane(0).data);
}
} // namespace shared
} // namespace raspi
} // namespace starboard