blob: f09335b9b7437731b228f6de3eac4ff57e65b1e7 [file] [log] [blame]
// Copyright 2016 The Cobalt Authors. 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.
#ifndef COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_
#define COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_
#include <algorithm>
#include <stack>
#include "base/logging.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/math/vector2d_f.h"
#include "cobalt/render_tree/brush.h"
#include "starboard/blitter.h"
#if SB_API_VERSION < 12 && SB_HAS(BLITTER)
namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace blitter {
// Keeps track of the current scale/offset transforms. Note that while the
// render tree supports general affine transformations, the Starboard Blitter
// API only supports scale and translations, so we maintain only those. If
// rotations are used, we can fallback to software rendering.
class Transform {
public:
Transform() : scale_(1.0f, 1.0f), translate_(0.0f, 0.0f) {}
explicit Transform(const math::Matrix3F& matrix)
: scale_(matrix.Get(0, 0), matrix.Get(1, 1)),
translate_(matrix.Get(0, 2), matrix.Get(1, 2)) {
// We cannot handle sheers and rotations.
DCHECK_EQ(0, matrix.Get(0, 1));
DCHECK_EQ(0, matrix.Get(1, 0));
}
Transform(const math::Vector2dF& scale, const math::Vector2dF& translate)
: scale_(scale), translate_(translate) {}
const math::Vector2dF& scale() const { return scale_; }
const math::Vector2dF& translate() const { return translate_; }
void ApplyOffset(const math::Vector2dF& offset) {
translate_ +=
math::Vector2dF(scale_.x() * offset.x(), scale_.y() * offset.y());
}
void ApplyScale(const math::Vector2dF& scale_mult) {
scale_.Scale(scale_mult.x(), scale_mult.y());
}
math::RectF TransformRect(const math::RectF& rect) const {
return math::RectF(rect.x() * scale_.x() + translate_.x(),
rect.y() * scale_.y() + translate_.y(),
rect.width() * scale_.x(), rect.height() * scale_.y());
}
math::Matrix3F ToMatrix() const {
return math::Matrix3F::FromValues(scale_.x(), 0, translate_.x(), 0,
scale_.y(), translate_.y(), 0, 0, 1);
}
private:
math::Vector2dF scale_;
math::Vector2dF translate_;
};
// Helper class to manage the pushing and popping of rectangular bounding
// boxes. This manages intersecting newly pushed bounding boxes with the
// existing stack of bounding boxes.
class BoundsStack {
public:
// Helper class to scope a pair of Push()/Pop() calls.
class ScopedPush {
public:
ScopedPush(BoundsStack* stack, const math::Rect& bounds) : stack_(stack) {
stack_->Push(bounds);
}
~ScopedPush() { stack_->Pop(); }
private:
BoundsStack* stack_;
};
BoundsStack(SbBlitterContext context, const math::Rect& initial_bounds);
void Push(const math::Rect& bounds);
void Pop();
const math::Rect& Top() const { return bounds_.top(); }
// Updates the SbBlitterContext object with the current top of the stack.
void UpdateContext();
private:
SbBlitterContext context_;
std::stack<math::Rect> bounds_;
};
// The full render state used by the Blitter API RenderTreeNodeVisitor.
// Packages together a render target, current transform and clip stack.
struct RenderState {
RenderState(SbBlitterRenderTarget render_target, const Transform& transform,
const BoundsStack& bounds_stack)
: render_target(render_target),
transform(transform),
bounds_stack(bounds_stack),
opacity(1.0f)
#if defined(ENABLE_DEBUGGER)
,
highlight_software_draws(false)
#endif // defined(ENABLE_DEBUGGER)
{
}
SbBlitterRenderTarget render_target;
Transform transform;
BoundsStack bounds_stack;
float opacity;
#if defined(ENABLE_DEBUGGER)
// If true, all software rasterization results are replaced with a green
// fill rectangle. Thus, if the software cache is used, one will see a flash
// of green every time something is registered with the cache.
bool highlight_software_draws;
#endif // defined(ENABLE_DEBUGGER)
};
} // namespace blitter
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt
#endif // SB_API_VERSION < 12 && SB_HAS(BLITTER)
#endif // COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_