Import Cobalt 13.103922
Change-Id: I06559c46741bb6050da0b0677b55c71bf6880784
diff --git a/src/cobalt/browser/browser_module.cc b/src/cobalt/browser/browser_module.cc
index 4322073..a1f944d 100644
--- a/src/cobalt/browser/browser_module.cc
+++ b/src/cobalt/browser/browser_module.cc
@@ -1269,7 +1269,9 @@
// render tree resources either.
main_web_module_layer_->Reset();
splash_screen_layer_->Reset();
+#if defined(ENABLE_DEBUG_CONSOLE)
debug_console_layer_->Reset();
+#endif // defined(ENABLE_DEBUG_CONSOLE)
#if defined(ENABLE_GPU_ARRAY_BUFFER_ALLOCATOR)
// Note that the following function call will leak the GPU memory allocated.
diff --git a/src/cobalt/browser/browser_module.h b/src/cobalt/browser/browser_module.h
index 6f95f5c..2ecdbcf 100644
--- a/src/cobalt/browser/browser_module.h
+++ b/src/cobalt/browser/browser_module.h
@@ -396,8 +396,10 @@
// Manages the three render trees, combines and renders them.
RenderTreeCombiner render_tree_combiner_;
scoped_ptr<RenderTreeCombiner::Layer> main_web_module_layer_;
- scoped_ptr<RenderTreeCombiner::Layer> debug_console_layer_;
scoped_ptr<RenderTreeCombiner::Layer> splash_screen_layer_;
+#if defined(ENABLE_DEBUG_CONSOLE)
+ scoped_ptr<RenderTreeCombiner::Layer> debug_console_layer_;
+#endif // defined(ENABLE_DEBUG_CONSOLE)
#if defined(ENABLE_SCREENSHOT)
// Helper object to create screen shots of the last layout tree.
diff --git a/src/cobalt/browser/testdata/mtm-demo/README.txt b/src/cobalt/browser/testdata/mtm-demo/README.txt
deleted file mode 100644
index 5368357..0000000
--- a/src/cobalt/browser/testdata/mtm-demo/README.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-These test whether the presence of the CSS MTM filter affect the path taken in
-rendering the video replaced box. <normal.html> has a video tag without the
-filter, while <mtm.html> has a video with the filter applied to it.
-
-To test locally, all 3 of mtm.html, normal.html and progressive.mp4 have to be
-hosted on a server that supports HTTP RANGE header, which is needed for video to
-be loaded correctly. One such server is the extension to the Python
-SimpleHTTPServer at https://github.com/danvk/RangeHTTPServer (run from this
-directory, "cobalt/src/cobalt/browser/testdata/mtm-demo/"):
-
- $ sudo apt-get install python-pip
- $ pip install --user rangehttpserver
- $ python -m RangeHTTPServer
-
-Test video without the MTM filter (should render normally, run from cobalt/src
-directory):
-
- $ out/linux-x64x11_debug/cobalt --csp_mode=disable --allow_http --url=http://localhost:8000/normal.html
-
-Test the video with the MTM filter (should NOT render in its bounding box in the
-document, and in the presence of the correct rasterizer, should be rendered onto
-its own texture off the main UI layout):
-
- $ out/linux-x64x11_debug/cobalt --csp_mode=disable --allow_http --url=http://localhost:8000/mtm.html
-
-There is also the option of using the google cloud utils and the cloud storage
-to publish these files, as is done with the other demos. Care should be taken
-that nothing confidential gets uploaded with these files. "public-read" is
-needed in the ACL because linking and video srcing does not work without it.
-
-A bucket specifically for this demo already exists at "gs://yt-cobalt-mtm-test",
-but uploading to it often might be problematic since buckets are not verison-
-controlled:
-
- $ gsutil cp -a public-read cobalt/browser/testdata/mtm-demo/normal.html cobalt/browser/testdata/mtm-demo/mtm.html cobalt/browser/testdata/mtm-demo/progressive.mp4 gs://yt-cobalt-mtm-test/
- $ out/linux-x64x11_debug/cobalt --csp_mode=disable --url=https://storage.googleapis.com/yt-cobalt-mtm-test/mtm.html
- $ out/linux-x64x11_debug/cobalt --csp_mode=disable --url=https://storage.googleapis.com/yt-cobalt-mtm-test/normal.html
diff --git a/src/cobalt/browser/testdata/mtm-demo/mtm.html b/src/cobalt/browser/testdata/mtm-demo/mtm.html
index 6877674..e91a3cc 100644
--- a/src/cobalt/browser/testdata/mtm-demo/mtm.html
+++ b/src/cobalt/browser/testdata/mtm-demo/mtm.html
@@ -1,28 +1,77 @@
<!DOCTYPE html>
<html>
+
<head>
- <title>mtm Demo</title>
+ <title>Map-To-Mesh Demo</title>
+
<style>
- body {
- background-color: rgb(255, 255, 255);
- color: #0047ab;
- font-size: 100px;
+ #v {
+ width: 100%;
+ height: 100%;
+ filter: map-to-mesh(equirectangular, 100deg 60deg,
+ matrix3d(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1));
}
- .vid {
- margin: 100px;
- border: 10px solid blue;
- width: 960px;
- height: 540px;
- filter: -cobalt-mtm(url(projection.msh), 100deg 60deg,
- matrix3d(1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1));
+
+ .instructions {
+ position: absolute;
+ left: 0;
+ background-color: white;
+ color: black;
}
</style>
+
+ <script>
+ var degreesPerSecond = 90;
+ // The following mappings are done in this order:
+ // Up, Down, Left, Right
+
+ // Direction keys
+ camera3D.createKeyMapping(38, camera3D.DOM_CAMERA_PITCH, degreesPerSecond);
+ camera3D.createKeyMapping(40, camera3D.DOM_CAMERA_PITCH, -degreesPerSecond);
+ camera3D.createKeyMapping(37, camera3D.DOM_CAMERA_YAW, degreesPerSecond);
+ camera3D.createKeyMapping(39, camera3D.DOM_CAMERA_YAW, -degreesPerSecond);
+
+ // DPAD
+ camera3D.createKeyMapping(
+ 0x800C, camera3D.DOM_CAMERA_PITCH, degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x800D, camera3D.DOM_CAMERA_PITCH, -degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x800E, camera3D.DOM_CAMERA_YAW, degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x800F, camera3D.DOM_CAMERA_YAW, -degreesPerSecond);
+
+ // Left joystick
+ camera3D.createKeyMapping(
+ 0x8011, camera3D.DOM_CAMERA_PITCH, degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x8012, camera3D.DOM_CAMERA_PITCH, -degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x8013, camera3D.DOM_CAMERA_YAW, degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x8014, camera3D.DOM_CAMERA_YAW, -degreesPerSecond);
+
+ // Right joystick
+ camera3D.createKeyMapping(
+ 0x8015, camera3D.DOM_CAMERA_PITCH, degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x8016, camera3D.DOM_CAMERA_PITCH, -degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x8017, camera3D.DOM_CAMERA_YAW, degreesPerSecond);
+ camera3D.createKeyMapping(
+ 0x8018, camera3D.DOM_CAMERA_YAW, -degreesPerSecond);
+ </script>
</head>
+
<body>
- <div>Mtm Demo!!!</div>
- <video autoplay loop id="v" class="vid" src="progressive.mp4"></video>
+ <video autoplay loop id="v" src="progressive.mp4"></video>
+ <div class="instructions">
+ Use either the keyboard keys, direction keys, or analog joystick/thumbstick
+ to look around.
+ </div>
</body>
+
</html>
diff --git a/src/cobalt/browser/testdata/mtm-demo/progressive.mp4 b/src/cobalt/browser/testdata/mtm-demo/progressive.mp4
deleted file mode 100644
index 2686a9b..0000000
--- a/src/cobalt/browser/testdata/mtm-demo/progressive.mp4
+++ /dev/null
Binary files differ
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 36f609f..d4d1d7c 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-103164
\ No newline at end of file
+103922
\ No newline at end of file
diff --git a/src/cobalt/cssom/computed_style.cc b/src/cobalt/cssom/computed_style.cc
index a59143a..a26c451 100644
--- a/src/cobalt/cssom/computed_style.cc
+++ b/src/cobalt/cssom/computed_style.cc
@@ -613,6 +613,8 @@
class ComputedHeightProvider : public NotReachedPropertyValueVisitor {
public:
ComputedHeightProvider(const PropertyValue* parent_computed_height,
+ const PropertyValue* parent_computed_top,
+ const PropertyValue* parent_computed_bottom,
const LengthValue* computed_font_size,
const LengthValue* root_computed_font_size,
const math::Size& viewport_size, bool out_of_flow);
@@ -627,6 +629,8 @@
private:
const PropertyValue* parent_computed_height_;
+ const PropertyValue* parent_computed_top_;
+ const PropertyValue* parent_computed_bottom_;
const LengthValue* computed_font_size_;
const LengthValue* root_computed_font_size_;
const math::Size& viewport_size_;
@@ -639,10 +643,14 @@
ComputedHeightProvider::ComputedHeightProvider(
const PropertyValue* parent_computed_height,
+ const PropertyValue* parent_computed_top,
+ const PropertyValue* parent_computed_bottom,
const LengthValue* computed_font_size,
const LengthValue* root_computed_font_size, const math::Size& viewport_size,
bool out_of_flow)
: parent_computed_height_(parent_computed_height),
+ parent_computed_top_(parent_computed_top),
+ parent_computed_bottom_(parent_computed_bottom),
computed_font_size_(computed_font_size),
root_computed_font_size_(root_computed_font_size),
viewport_size_(viewport_size),
@@ -725,7 +733,10 @@
// (i.e., it depends on content height), and this element is not absolutely
// positioned, the value computes to "auto".
// https://www.w3.org/TR/CSS21/visudet.html#the-height-property
- computed_height_ = (parent_computed_height_ == auto_value && !out_of_flow_)
+ computed_height_ = (parent_computed_height_ == auto_value &&
+ (parent_computed_top_ == auto_value ||
+ parent_computed_bottom_ == auto_value) &&
+ !out_of_flow_)
? auto_value
: percentage;
}
@@ -2858,7 +2869,9 @@
} break;
case kHeightProperty: {
ComputedHeightProvider height_provider(
- parent_computed_style_.height().get(), GetFontSize(),
+ parent_computed_style_.height().get(),
+ parent_computed_style_.top().get(),
+ parent_computed_style_.bottom().get(), GetFontSize(),
GetRootFontSize(), GetViewportSizeOnePercent(),
IsAbsolutelyPositioned());
(*value)->Accept(&height_provider);
diff --git a/src/cobalt/dom/url_utils.cc b/src/cobalt/dom/url_utils.cc
index df204d1..57604bd 100644
--- a/src/cobalt/dom/url_utils.cc
+++ b/src/cobalt/dom/url_utils.cc
@@ -14,9 +14,76 @@
#include "cobalt/dom/url_utils.h"
+namespace {
+// Returns true if the url can have non-opaque origin.
+// Blob URLs needs to be pre-processed.
+bool NonBlobURLCanHaveTupleOrigin(const GURL& url) {
+ if (url.SchemeIs("https")) {
+ return true;
+ } else if (url.SchemeIs("http")) {
+ return true;
+ } else if (url.SchemeIs("ftp")) {
+ return true;
+ } else if (url.SchemeIs("ws")) {
+ return true;
+ } else if (url.SchemeIs("wss")) {
+ return true;
+ }
+ return false;
+}
+// Returns false if url should be opaque.
+// Otherwise, extract origin tuple from the url and assemble them as a string
+// for easier access and comparison.
+bool NonBlobURLGetOriginStr(const GURL& url, std::string* output) {
+ if (!NonBlobURLCanHaveTupleOrigin(url)) {
+ return false;
+ }
+ *output = url.scheme() + "://" + url.host() +
+ (url.has_port() ? ":" + url.port() : "");
+ return true;
+}
+} // namespace
+
namespace cobalt {
namespace dom {
+URLUtils::Origin::Origin() : is_opaque_(true) {}
+
+URLUtils::Origin::Origin(const GURL& url) : is_opaque_(false) {
+ if (url.is_valid() && url.has_scheme() && url.has_host()) {
+ if (url.SchemeIs("blob")) {
+ // Let path_url be the result of parsing URL's path.
+ // Return a new opaque origin, if url is failure, and url's origin
+ // otherwise.
+ GURL path_url(url.path());
+ if (path_url.is_valid() && path_url.has_host() && path_url.has_scheme() &&
+ NonBlobURLGetOriginStr(path_url, &origin_str_)) {
+ return;
+ }
+ } else if (NonBlobURLGetOriginStr(url, &origin_str_)) {
+ // Assign a tuple origin if given url is allowed to have one.
+ return;
+ }
+ }
+ // Othwise, return a new opaque origin.
+ is_opaque_ = true;
+}
+
+std::string URLUtils::Origin::SerializedOrigin() const {
+ if (is_opaque_) {
+ return "null";
+ }
+ return origin_str_;
+}
+
+bool URLUtils::Origin::operator==(const Origin& rhs) const {
+ if (is_opaque_ || rhs.is_opaque_) {
+ return false;
+ } else {
+ return origin_str_ == rhs.origin_str_;
+ }
+}
+
URLUtils::URLUtils(const GURL& url, bool is_opaque)
: url_(url), origin_(is_opaque ? Origin() : Origin(url)) {}
URLUtils::URLUtils(const GURL& url, const UpdateStepsCallback& update_steps,
diff --git a/src/cobalt/dom/url_utils.h b/src/cobalt/dom/url_utils.h
index af3f3ad..aa66825 100644
--- a/src/cobalt/dom/url_utils.h
+++ b/src/cobalt/dom/url_utils.h
@@ -20,36 +20,6 @@
#include "base/callback.h"
#include "googleurl/src/gurl.h"
-namespace {
-// Returns true if the url can have non-opaque origin.
-// Blob URLs needs to be pre-processed.
-bool NonBlobURLCanHaveTupleOrigin(const GURL& url) {
- if (url.SchemeIs("https")) {
- return true;
- } else if (url.SchemeIs("http")) {
- return true;
- } else if (url.SchemeIs("ftp")) {
- return true;
- } else if (url.SchemeIs("ws")) {
- return true;
- } else if (url.SchemeIs("wss")) {
- return true;
- }
- return false;
-}
-// Returns false if url should be opaque.
-// Otherwise, extract origin tuple from the url and assemble them as a string
-// for easier access and comparison.
-bool NonBlobURLGetOriginStr(const GURL& url, std::string* output) {
- if (!NonBlobURLCanHaveTupleOrigin(url)) {
- return false;
- }
- *output = url.scheme() + "://" + url.host() +
- (url.has_port() ? ":" + url.port() : "");
- return true;
-}
-} // namespace
-
namespace cobalt {
namespace dom {
@@ -69,48 +39,19 @@
class Origin {
public:
// To create an opaque origin, use Origin().
- Origin() : is_opaque_(true) {}
+ Origin();
// Initialize an origin to the url's origin.
// https://url.spec.whatwg.org/#concept-url-origin
- Origin(const GURL& url) : is_opaque_(false) {
- if (url.is_valid() && url.has_scheme() && url.has_host()) {
- if (url.SchemeIs("blob")) {
- // Let path_url be the result of parsing URL's path.
- // Return a new opaque origin, if url is failure, and url's origin
- // otherwise.
- GURL path_url(url.path());
- if (path_url.is_valid() && path_url.has_host() &&
- path_url.has_scheme() &&
- NonBlobURLGetOriginStr(path_url, &origin_str_)) {
- return;
- }
- } else if (NonBlobURLGetOriginStr(url, &origin_str_)) {
- // Assign a tuple origin if given url is allowed to have one.
- return;
- }
- }
- // Othwise, return a new opaque origin.
- is_opaque_ = true;
- }
+ explicit Origin(const GURL& url);
// https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin
- std::string SerializedOrigin() const {
- if (is_opaque_) {
- return "null";
- }
- return origin_str_;
- }
+ std::string SerializedOrigin() const;
+ bool is_opaque() const { return is_opaque_; }
// Only document has an origin and no elements inherit document's origin, so
// opaque origin comparison can always return false.
// https://html.spec.whatwg.org/multipage/origin.html#same-origin
- bool operator==(const Origin& rhs) {
- if (is_opaque_ || rhs.is_opaque_) {
- return false;
- } else {
- return origin_str_ == rhs.origin_str_;
- }
- }
+ bool operator==(const Origin& rhs) const;
// Returns true if two origins are different(cross-origin).
- bool operator!=(const Origin& rhs) { return !(*this == rhs); }
+ bool operator!=(const Origin& rhs) const { return !(*this == rhs); }
private:
bool is_opaque_;
diff --git a/src/cobalt/layout/block_container_box.cc b/src/cobalt/layout/block_container_box.cc
index 80d1edd..557b666 100644
--- a/src/cobalt/layout/block_container_box.cc
+++ b/src/cobalt/layout/block_container_box.cc
@@ -110,8 +110,14 @@
// it depends on content height), and this element is not absolutely
// positioned, the value [of "height"] computes to "auto".
// https://www.w3.org/TR/CSS21/visudet.html#the-height-property
- child_layout_params.containing_block_size.set_height(
- maybe_height.value_or(LayoutUnit()));
+ if (maybe_height) {
+ child_layout_params.containing_block_size.set_height(*maybe_height);
+ } else if (maybe_top && maybe_bottom) {
+ child_layout_params.containing_block_size.set_height(
+ containing_block_size.height() - *maybe_top - *maybe_bottom);
+ } else {
+ child_layout_params.containing_block_size.set_height(LayoutUnit());
+ }
}
scoped_ptr<FormattingContext> formatting_context =
UpdateRectOfInFlowChildBoxes(child_layout_params);
diff --git a/src/cobalt/layout/box.cc b/src/cobalt/layout/box.cc
index 38c644f..c8ed055 100644
--- a/src/cobalt/layout/box.cc
+++ b/src/cobalt/layout/box.cc
@@ -547,21 +547,11 @@
render_tree::CompositionNode::Builder border_node_builder(border_box_offset);
AnimateNode::Builder animate_node_builder;
- base::optional<RoundedCorners> rounded_corners = ComputeRoundedCorners();
+ const base::optional<RoundedCorners> rounded_corners =
+ ComputeRoundedCorners();
- // If we have rounded corners and a non-zero border, then we need to compute
- // the "inner" rounded corners, as the ones specified by CSS apply to the
- // outer border edge.
- base::optional<RoundedCorners> padding_rounded_corners_if_different;
- if (rounded_corners && !border_insets_.zero()) {
- padding_rounded_corners_if_different = rounded_corners->Inset(math::InsetsF(
- border_insets_.left().toFloat(), border_insets_.top().toFloat(),
- border_insets_.right().toFloat(), border_insets_.bottom().toFloat()));
- }
- const base::optional<RoundedCorners>& padding_rounded_corners =
- padding_rounded_corners_if_different
- ? padding_rounded_corners_if_different
- : rounded_corners;
+ const base::optional<RoundedCorners> padding_rounded_corners =
+ ComputePaddingRoundedCorners(rounded_corners);
// The painting order is:
// - background color.
@@ -594,8 +584,8 @@
}
RenderAndAnimateBorder(rounded_corners, &border_node_builder,
&animate_node_builder);
- RenderAndAnimateBoxShadow(rounded_corners, &border_node_builder,
- &animate_node_builder);
+ RenderAndAnimateBoxShadow(rounded_corners, padding_rounded_corners,
+ &border_node_builder, &animate_node_builder);
}
const bool overflow_hidden =
@@ -744,8 +734,7 @@
if (rounded_corners) {
rect_node_builder->rounded_corners =
- scoped_ptr<RoundedCorners>(new RoundedCorners(
- rounded_corners->Normalize(rect_node_builder->rect)));
+ scoped_ptr<RoundedCorners>(new RoundedCorners(*rounded_corners));
}
}
@@ -834,8 +823,7 @@
if (rounded_corners) {
rect_node_builder->rounded_corners =
- scoped_ptr<RoundedCorners>(new RoundedCorners(
- rounded_corners->Normalize(rect_node_builder->rect)));
+ scoped_ptr<RoundedCorners>(new RoundedCorners(*rounded_corners));
}
}
@@ -1225,7 +1213,7 @@
} // namespace
-base::optional<render_tree::RoundedCorners> Box::ComputeRoundedCorners() {
+base::optional<render_tree::RoundedCorners> Box::ComputeRoundedCorners() const {
UsedBorderRadiusProvider border_radius_provider(GetBorderBoxSize());
render_tree::RoundedCorner border_top_left_radius;
render_tree::RoundedCorner border_top_right_radius;
@@ -1269,13 +1257,36 @@
rounded_corners.emplace(border_top_left_radius, border_top_right_radius,
border_bottom_right_radius,
border_bottom_left_radius);
+ rounded_corners =
+ rounded_corners->Normalize(math::RectF(GetBorderBoxSize()));
}
return rounded_corners;
}
+base::optional<render_tree::RoundedCorners> Box::ComputePaddingRoundedCorners(
+ const base::optional<RoundedCorners>& rounded_corners) const {
+ base::optional<RoundedCorners> padding_rounded_corners_if_different;
+
+ if (rounded_corners && !border_insets_.zero()) {
+ // If we have rounded corners and a non-zero border, then we need to
+ // compute the "inner" rounded corners, as the ones specified by CSS apply
+ // to the outer border edge.
+ padding_rounded_corners_if_different = rounded_corners->Inset(math::InsetsF(
+ border_insets_.left().toFloat(), border_insets_.top().toFloat(),
+ border_insets_.right().toFloat(), border_insets_.bottom().toFloat()));
+ }
+
+ const base::optional<RoundedCorners>& padding_rounded_corners =
+ padding_rounded_corners_if_different
+ ? padding_rounded_corners_if_different
+ : rounded_corners;
+ return padding_rounded_corners;
+}
+
void Box::RenderAndAnimateBoxShadow(
- const base::optional<RoundedCorners>& rounded_corners,
+ const base::optional<RoundedCorners>& outer_rounded_corners,
+ const base::optional<RoundedCorners>& inner_rounded_corners,
CompositionNode::Builder* border_node_builder,
AnimateNode::Builder* animate_node_builder) {
UNREFERENCED_PARAMETER(animate_node_builder);
@@ -1327,9 +1338,13 @@
render_tree::RectShadowNode::Builder shadow_builder(
math::RectF(rect_offset, shadow_rect_size), shadow,
shadow_value->has_inset(), spread_radius);
- if (rounded_corners) {
- shadow_builder.rounded_corners = rounded_corners->Normalize(
- shadow_builder.rect);
+
+ if (outer_rounded_corners) {
+ if (shadow_value->has_inset()) {
+ shadow_builder.rounded_corners = inner_rounded_corners;
+ } else {
+ shadow_builder.rounded_corners = outer_rounded_corners;
+ }
}
// Finally, create our shadow node.
@@ -1484,8 +1499,7 @@
// Apply rounded viewport filter to the background image.
FilterNode::Builder filter_node_builder(background_node);
filter_node_builder.viewport_filter =
- ViewportFilter(image_frame,
- rounded_corners->Normalize(image_frame));
+ ViewportFilter(image_frame, *rounded_corners);
background_node = new FilterNode(filter_node_builder);
}
@@ -1548,18 +1562,11 @@
scoped_refptr<render_tree::Node> Box::RenderAndAnimateOverflow(
const scoped_refptr<render_tree::Node>& content_node,
const math::Vector2dF& border_offset) {
- base::optional<RoundedCorners> rounded_corners = ComputeRoundedCorners();
+ const base::optional<RoundedCorners> rounded_corners =
+ ComputeRoundedCorners();
- base::optional<RoundedCorners> padding_rounded_corners_if_different;
- if (rounded_corners && !border_insets_.zero()) {
- padding_rounded_corners_if_different = rounded_corners->Inset(math::InsetsF(
- border_insets_.left().toFloat(), border_insets_.top().toFloat(),
- border_insets_.right().toFloat(), border_insets_.bottom().toFloat()));
- }
- const base::optional<RoundedCorners>& padding_rounded_corners =
- padding_rounded_corners_if_different
- ? padding_rounded_corners_if_different
- : rounded_corners;
+ const base::optional<RoundedCorners> padding_rounded_corners =
+ ComputePaddingRoundedCorners(rounded_corners);
return RenderAndAnimateOverflow(padding_rounded_corners, content_node, NULL,
border_offset);
@@ -1584,9 +1591,7 @@
border_node_offset.y() + border_top_width().toFloat(),
padding_size.width(), padding_size.height()));
if (rounded_corners) {
- filter_node_builder.viewport_filter->set_rounded_corners(
- rounded_corners->Normalize(
- filter_node_builder.viewport_filter->viewport()));
+ filter_node_builder.viewport_filter->set_rounded_corners(*rounded_corners);
}
return scoped_refptr<render_tree::Node>(new FilterNode(filter_node_builder));
diff --git a/src/cobalt/layout/box.h b/src/cobalt/layout/box.h
index 67056ab..dda5300 100644
--- a/src/cobalt/layout/box.h
+++ b/src/cobalt/layout/box.h
@@ -699,8 +699,13 @@
// Updates used values of "padding" properties.
void UpdatePaddings(const LayoutParams& layout_params);
- // Computes the rounded corners (if there are any) from the border radii.
- base::optional<render_tree::RoundedCorners> ComputeRoundedCorners();
+ // Computes the normalized "outer" rounded corners (if there are any) from the
+ // border radii.
+ base::optional<render_tree::RoundedCorners> ComputeRoundedCorners() const;
+
+ // Computes the corresponding "inner" rounded corners.
+ base::optional<render_tree::RoundedCorners> ComputePaddingRoundedCorners(
+ const base::optional<render_tree::RoundedCorners>& rounded_corners) const;
// Called after TryPlaceEllipsisOrProcessPlacedEllipsis() determines that the
// box is impacted by the ellipsis. This handles both determining the location
@@ -736,7 +741,8 @@
RenderAndAnimateBackgroundImageResult RenderAndAnimateBackgroundImage(
const base::optional<render_tree::RoundedCorners>& rounded_corners);
void RenderAndAnimateBoxShadow(
- const base::optional<render_tree::RoundedCorners>& rounded_corners,
+ const base::optional<render_tree::RoundedCorners>& outer_rounded_corners,
+ const base::optional<render_tree::RoundedCorners>& inner_rounded_corners,
render_tree::CompositionNode::Builder* border_node_builder,
render_tree::animations::AnimateNode::Builder* animate_node_builder);
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/10-5-percentage-of-height-should-work-properly-with-top-and-bottom-expected.png b/src/cobalt/layout_tests/testdata/css-2-1/10-5-percentage-of-height-should-work-properly-with-top-and-bottom-expected.png
new file mode 100644
index 0000000..6b01be2
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css-2-1/10-5-percentage-of-height-should-work-properly-with-top-and-bottom-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/10-5-percentage-of-height-should-work-properly-with-top-and-bottom.html b/src/cobalt/layout_tests/testdata/css-2-1/10-5-percentage-of-height-should-work-properly-with-top-and-bottom.html
new file mode 100644
index 0000000..3e23d27
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css-2-1/10-5-percentage-of-height-should-work-properly-with-top-and-bottom.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+ | If the height of the child is a percent of the height of the containing
+ | block and the containing block's height is produced from top and bottom,
+ | the height of the child should be properly calculated.
+ | https://www.w3.org/TR/CSS21/visudet.html#the-height-property
+ | https://www.w3.org/TR/CSS21/visuren.html#propdef-top
+ | https://www.w3.org/TR/CSS21/visuren.html#propdef-bottom
+ -->
+<html>
+<head>
+ <style">
+ body {
+ background-color: #FFFFFF;
+ }
+ .container {
+ position: absolute;
+ height: 300px;
+ width: 100px;
+ }
+ .top-bottom {
+ background-color: #EA4335;
+ position: absolute;
+ top: 10px;
+ bottom: 0px;
+ left: 10px;
+ width: 100px;
+ }
+ .percent-height {
+ background-color: #4285F4;
+ height: 100%;
+ position: relative;
+ }
+ </style>
+</head>
+<body>
+ <div class="container">
+ <div class="top-bottom">
+ <div class="percent-height"></div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt b/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt
index 995b02a..37e4c1e 100644
--- a/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/css-2-1/layout_tests.txt
@@ -43,6 +43,7 @@
10-4-min-width-and-max-width-percentage-should-refer-containing-block-width
10-5-percentage-of-auto-height-on-absolute-element-should-compute-to-percentage
10-5-percentage-of-auto-height-should-compute-to-auto
+10-5-percentage-of-height-should-work-properly-with-top-and-bottom
10-6-1-content-height-of-inline-boxes-matches-font-size
10-6-2-replaced-box-height
10-8-1-inline-box-with-non-normal-line-height-should-use-first-available-font-for-font-metrics
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border-and-inset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border-and-inset-shadow.html
new file mode 100644
index 0000000..a46b00a
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border-and-inset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 2 values for the border radius for a box with a background color,
+ | a border and an inset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 100px;
+ box-shadow: 10px 10px #FF7F50 inset;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border-and-outset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border-and-outset-shadow.html
new file mode 100644
index 0000000..1cc1359
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border-and-outset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 2 values for the border radius for a box with a background color,
+ | a border and an outset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 100px;
+ box-shadow: 10px 10px #FF7F50;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border.html
new file mode 100644
index 0000000..63e2826
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-2-values-with-background-color-and-border.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+ | Setting 2 values for the border radius for a box with a background color
+ | and a border.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 100px;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border-and-inset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border-and-inset-shadow.html
new file mode 100644
index 0000000..93ab665
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border-and-inset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 3 values for the border radius for a box with a background color,
+ | a border and in inset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 10px 120px 50px;
+ box-shadow: 10px 10px #FF7F50 inset;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border-and-outset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border-and-outset-shadow.html
new file mode 100644
index 0000000..3e5517a
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border-and-outset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 3 values for the border radius for a box with a background color,
+ | a border and in outset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 10px 120px 50px;
+ box-shadow: 10px 10px #FF7F50;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border.html
new file mode 100644
index 0000000..7d26761
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-3-values-with-background-color-and-border.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+ | Setting 3 values for the border radius for a box with a background color
+ | and a border.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 10px 120px 50px;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border-and-inset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border-and-inset-shadow.html
new file mode 100644
index 0000000..4ec00df
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border-and-inset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 values for the border radius for a box with a background color,
+ | a border and an inset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 120px 40px 70px;
+ box-shadow: 10px 10px #FF7F50 inset;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border-and-outset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border-and-outset-shadow.html
new file mode 100644
index 0000000..256fe37
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border-and-outset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 values for the border radius for a box with a background color,
+ | a border and an outset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 120px 40px 70px;
+ box-shadow: 10px 10px #FF7F50;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border.html
new file mode 100644
index 0000000..c419580
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-4-values-with-background-color-and-border.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 values for the border radius for a box with a background color
+ | and a border.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 120px 40px 70px;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border-and-inset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border-and-inset-shadow.html
new file mode 100644
index 0000000..b969b0a
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border-and-inset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 values for the border radius for a box with a background color,
+ | a border and an inset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 100px 0px 75px;
+ box-shadow: 10px 10px #FF7F50 inset;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border-and-outset-shadow.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border-and-outset-shadow.html
new file mode 100644
index 0000000..3ec1d92
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border-and-outset-shadow.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 values for the border radius for a box with a background color,
+ | a border and an outset shadow.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 100px 0px 75px;
+ box-shadow: 10px 10px #FF7F50;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border.html b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border.html
new file mode 100644
index 0000000..390ecf9
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css3-background/5-0-border-radius-with-zero-value-and-background-color-and-border.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+ | Setting 4 values for the border radius for a box with a background color
+ | and a border.
+ | Note that this will not look the exact same in Chrome since Cobalt
+ | normalizes opposing corners and Chrome does not.
+ | https://www.w3.org/TR/css3-background/#border-radius
+ -->
+<html>
+<head>
+ <style>
+ div {
+ border: 25px solid rgb(255,192,203);
+ background-color: rgb(176,176,176);
+ border-radius: 50px 100px 0px 75px;
+ height: 200px;
+ width: 100px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/cobalt/loader/image/image_decoder.cc b/src/cobalt/loader/image/image_decoder.cc
index 50f1699..52a5f6a 100644
--- a/src/cobalt/loader/image/image_decoder.cc
+++ b/src/cobalt/loader/image/image_decoder.cc
@@ -19,11 +19,7 @@
#include "base/debug/trace_event.h"
#include "cobalt/loader/image/dummy_gif_image_decoder.h"
#include "cobalt/loader/image/image_decoder_starboard.h"
-#if defined(USE_PS3_JPEG_IMAGE_DECODER)
-#include "cobalt/loader/image/jpeg_image_decoder_ps3.h"
-#else // defined(USE_PS3_JPEG_IMAGE_DECODER)
#include "cobalt/loader/image/jpeg_image_decoder.h"
-#endif // defined(USE_PS3_JPEG_IMAGE_DECODER)
#include "cobalt/loader/image/png_image_decoder.h"
#include "cobalt/loader/image/stub_image_decoder.h"
#include "cobalt/loader/image/webp_image_decoder.h"
@@ -336,13 +332,8 @@
return make_scoped_ptr<ImageDataDecoder>(
new StubImageDecoder(resource_provider));
} else if (image_type == ImageDecoder::kImageTypeJPEG) {
-#if defined(USE_PS3_JPEG_IMAGE_DECODER)
- return make_scoped_ptr<ImageDataDecoder>(
- new JPEGImageDecoderPS3(resource_provider));
-#else // defined(USE_PS3_JPEG_IMAGE_DECODER)
return make_scoped_ptr<ImageDataDecoder>(
new JPEGImageDecoder(resource_provider));
-#endif // defined(USE_PS3_JPEG_IMAGE_DECODER)
} else if (image_type == ImageDecoder::kImageTypePNG) {
return make_scoped_ptr<ImageDataDecoder>(
new PNGImageDecoder(resource_provider));
diff --git a/src/cobalt/loader/loader.gyp b/src/cobalt/loader/loader.gyp
index 9a50b4e..1ab0435 100644
--- a/src/cobalt/loader/loader.gyp
+++ b/src/cobalt/loader/loader.gyp
@@ -97,12 +97,6 @@
'embed_resources_as_header_files',
],
'conditions': [
- ['target_arch == "ps3"', {
- 'sources': [
- 'image/jpeg_image_decoder_ps3.cc',
- 'image/jpeg_image_decoder_ps3.h',
- ],
- }],
['enable_about_scheme == 1', {
'defines': [ 'ENABLE_ABOUT_SCHEME' ],
'sources': [
diff --git a/src/cobalt/render_tree/rounded_corners.cc b/src/cobalt/render_tree/rounded_corners.cc
index 7eacb19..8149cd4 100644
--- a/src/cobalt/render_tree/rounded_corners.cc
+++ b/src/cobalt/render_tree/rounded_corners.cc
@@ -29,6 +29,7 @@
}
RoundedCorners RoundedCorners::Normalize(const math::RectF& rect) const {
+ const float kEpsilon = 0.0001f;
float scale = 1.0f;
float size;
@@ -38,27 +39,28 @@
size = top_left.horizontal +
std::max(top_right.horizontal, bottom_right.horizontal);
if (size > rect.width()) {
- scale = rect.width() / size;
+ scale = (rect.width() - kEpsilon) / size;
}
size = bottom_left.horizontal +
std::max(bottom_right.horizontal, top_right.horizontal);
if (size > rect.width()) {
- scale = std::min(rect.width() / size, scale);
+ scale = std::min((rect.width() - kEpsilon) / size, scale);
}
- size = top_left.vertical +
- std::max(bottom_left.vertical, bottom_right.vertical);
+ size =
+ top_left.vertical + std::max(bottom_left.vertical, bottom_right.vertical);
if (size > rect.height()) {
- scale = std::min(rect.height() / size, scale);
+ scale = std::min((rect.height() - kEpsilon) / size, scale);
}
size = top_right.vertical +
std::max(bottom_right.vertical, bottom_left.vertical);
if (size > rect.height()) {
- scale = std::min(rect.height() / size, scale);
+ scale = std::min((rect.height() - kEpsilon) / size, scale);
}
+ scale = std::max(scale, 0.0f);
return Scale(scale, scale);
}
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index 603eb8e..6b7ba0c 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -640,6 +640,11 @@
backend::GraphicsContextEGL::ScopedMakeCurrent scoped_make_current(
graphics_context_, render_target_egl);
+ // Make sure the render target's framebuffer is bound before continuing.
+ // Skia will usually do this, but it is possible for some render trees to
+ // have non-skia draw calls only, in which case this needs to be done.
+ GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER,
+ render_target_egl->GetPlatformHandle()));
// First reset the graphics context state for the pending render tree
// draw calls, in case we have modified state in between.
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index a8548ea..057bb38 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -53,7 +53,7 @@
// changes. It is reasonable to base a port on the Release Candidate API
// version, but be aware that small incompatible changes may still be made to
// it.
-#define SB_RELEASE_CANDIDATE_API_VERSION 6
+#define SB_RELEASE_CANDIDATE_API_VERSION 7
// --- Experimental Feature Defines ------------------------------------------
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index ea8d300..212a904 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
+# Copyright 2017 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.
@@ -80,5 +80,7 @@
test_filter.TestFilter(
'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
test_filter.TestFilter(
- 'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug')
+ 'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
+ test_filter.TestFilter(
+ 'starboard_platform_tests', test_filter.FILTER_ALL)
]
diff --git a/src/starboard/linux/x64directfb/__init__.py b/src/starboard/linux/x64directfb/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/starboard/linux/x64directfb/__init__.py
diff --git a/src/starboard/linux/x64directfb/future/gyp_configuration.py b/src/starboard/linux/x64directfb/future/gyp_configuration.py
index 1074bc3..446f822 100644
--- a/src/starboard/linux/x64directfb/future/gyp_configuration.py
+++ b/src/starboard/linux/x64directfb/future/gyp_configuration.py
@@ -16,7 +16,7 @@
import logging
# Import the shared Linux platform configuration.
-from starboard.linux.shared import gyp_configuration
+import starboard.linux.x64directfb.gyp_configuration as gyp_configuration
def CreatePlatformConfig():
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.py b/src/starboard/linux/x64directfb/gyp_configuration.py
index 7e60294..483e5dd 100644
--- a/src/starboard/linux/x64directfb/gyp_configuration.py
+++ b/src/starboard/linux/x64directfb/gyp_configuration.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
+# Copyright 2017 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.
@@ -16,17 +16,45 @@
import logging
# Import the shared Linux platform configuration.
-from starboard.linux.shared import gyp_configuration
+import starboard.linux.shared.gyp_configuration as gyp_configuration
+import starboard.tools.testing.test_filter as test_filter
def CreatePlatformConfig():
try:
- return gyp_configuration.PlatformConfig(
- 'linux-x64directfb',
- # Unfortunately, some memory leaks outside of our control, and difficult
- # to pattern match with ASAN's suppression list, appear in DirectFB
- # builds, and so this must be disabled.
- asan_enabled_by_default=False)
+ return PlatformConfig(
+ 'linux-x64directfb')
except RuntimeError as e:
logging.critical(e)
return None
+
+
+class PlatformConfig(gyp_configuration.PlatformConfig):
+
+ # Unfortunately, some memory leaks outside of our control, and difficult
+ # to pattern match with ASAN's suppression list, appear in DirectFB
+ # builds, and so this must be disabled.
+ def __init__(self, platform, asan_enabled_by_default=False,
+ goma_supported_by_compiler=True):
+ super(PlatformConfig, self).__init__(
+ platform, asan_enabled_by_default, goma_supported_by_compiler)
+
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return [
+ test_filter.TestFilter(
+ 'bindings_test', ('GlobalInterfaceBindingsTest.'
+ 'PropertiesAndOperationsAreOwnProperties')),
+ test_filter.TestFilter(
+ 'net_unittests', 'HostResolverImplDnsTest.DnsTaskUnspec'),
+ test_filter.TestFilter(
+ 'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+ test_filter.TestFilter(
+ 'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
+ test_filter.TestFilter(
+ 'starboard_platform_tests', test_filter.FILTER_ALL, 'debug')
+ ]
diff --git a/src/starboard/linux/x64x11/gyp_configuration.py b/src/starboard/linux/x64x11/gyp_configuration.py
index 6685818..9b4962f 100644
--- a/src/starboard/linux/x64x11/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/gyp_configuration.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
+# Copyright 2017 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.
@@ -16,6 +16,7 @@
import logging
from starboard.linux.shared import gyp_configuration
+import starboard.tools.testing.test_filter as test_filter
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
from starboard.tools.toolchain import clang
@@ -49,6 +50,26 @@
bash.Shell(),
]
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return [
+ test_filter.TestFilter(
+ 'bindings_test', ('GlobalInterfaceBindingsTest.'
+ 'PropertiesAndOperationsAreOwnProperties')),
+ test_filter.TestFilter(
+ 'net_unittests', 'HostResolverImplDnsTest.DnsTaskUnspec'),
+ test_filter.TestFilter(
+ 'nplb_blitter_pixel_tests', test_filter.FILTER_ALL),
+ test_filter.TestFilter(
+ 'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+ test_filter.TestFilter(
+ 'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
+ ]
+
def CreatePlatformConfig():
try:
diff --git a/src/starboard/linux/x64x11/mock/gyp_configuration.py b/src/starboard/linux/x64x11/mock/gyp_configuration.py
index ff41cea..fa14e09 100644
--- a/src/starboard/linux/x64x11/mock/gyp_configuration.py
+++ b/src/starboard/linux/x64x11/mock/gyp_configuration.py
@@ -17,7 +17,7 @@
import config.starboard
import gyp_utils
-
+import starboard.tools.testing.test_filter as test_filter
def CreatePlatformConfig():
try:
@@ -56,3 +56,25 @@
'CXX': self.host_compiler_environment['CXX_host'],
})
return env_variables
+
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return [
+ test_filter.TestFilter(
+ 'bindings_test', ('GlobalInterfaceBindingsTest.'
+ 'PropertiesAndOperationsAreOwnProperties')),
+ test_filter.TestFilter(
+ 'net_unittests', 'HostResolverImplDnsTest.DnsTaskUnspec'),
+ test_filter.TestFilter(
+ 'nplb_blitter_pixel_tests', test_filter.FILTER_ALL),
+ test_filter.TestFilter(
+ 'web_platform_tests', 'xhr/WebPlatformTest.Run/125', 'debug'),
+ test_filter.TestFilter(
+ 'web_platform_tests', 'streams/WebPlatformTest.Run/11', 'debug'),
+ test_filter.TestFilter(
+ 'starboard_platform_tests', test_filter.FILTER_ALL)
+ ]
diff --git a/src/starboard/raspi/shared/gyp_configuration.py b/src/starboard/raspi/shared/gyp_configuration.py
index f288584..a750f06 100644
--- a/src/starboard/raspi/shared/gyp_configuration.py
+++ b/src/starboard/raspi/shared/gyp_configuration.py
@@ -19,6 +19,7 @@
import config.starboard
import gyp_utils
+import starboard.tools.testing.test_filter as test_filter
class RaspiPlatformConfig(config.starboard.PlatformConfigStarboard):
@@ -64,3 +65,44 @@
'CXX': os.path.join(toolchain_bin_dir, 'arm-linux-gnueabihf-g++'),
})
return env_variables
+
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return [
+ # Fails with SpiderMonkey.
+ test_filter.TestFilter(
+ 'bindings_test', ('GlobalInterfaceBindingsTest.'
+ 'PropertiesAndOperationsAreOwnProperties')),
+ test_filter.TestFilter(
+ 'net_unittests', 'HostResolverImplDnsTest.DnsTaskUnspec'),
+
+ # The RasPi test devices don't have access to an IPV6 network, so
+ # disable the related tests.
+ test_filter.TestFilter(
+ 'nplb', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.'
+ 'SunnyDayDestination/1'),
+ test_filter.TestFilter(
+ 'nplb', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.'
+ 'SunnyDaySourceForDestination/1'),
+ test_filter.TestFilter(
+ 'nplb', 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.'
+ 'SunnyDaySourceNotLoopback/1'),
+
+ # These tests are currently producing slightly different images on the
+ # RasPi.
+ test_filter.TestFilter(
+ 'renderer_test', 'PixelTest.CircularSubPixelBorder'),
+ test_filter.TestFilter(
+ 'renderer_test', 'PixelTest.FilterBlurred100PxText'),
+
+ test_filter.TestFilter('starboard_platform_tests',
+ test_filter.FILTER_ALL),
+ test_filter.TestFilter('nplb_blitter_pixel_tests',
+ test_filter.FILTER_ALL),
+ test_filter.TestFilter('web_platform_tests', test_filter.FILTER_ALL)
+
+ ]
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
index 7138894..6fd98c6 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.cc
@@ -94,20 +94,8 @@
if (frames_.empty()) {
return last_displayed_frame_;
}
- // Remove any frames with timestamps earlier than |media_time|, but always
- // keep at least one of the frames.
- while (frames_.size() > 1 && frames_.front()->pts() < media_time) {
- if (frames_.front() != last_displayed_frame_) {
- ++dropped_frames_;
- }
- frames_.pop_front();
- }
- if (audio_eos_reached) {
- while (frames_.size() > 1) {
- frames_.pop_back();
- }
- }
+ AdvanceTime(media_time, audio_eos_reached);
last_displayed_frame_ = frames_.front();
return last_displayed_frame_;
@@ -157,11 +145,30 @@
need_more_input_ = (status == VideoDecoder::kNeedMoreInput);
}
+void VideoRendererImpl::AdvanceTime(
+ SbMediaTime media_time, bool audio_eos_reached) {
+ while (frames_.size() > 1 && frames_.front()->pts() < media_time) {
+ if (frames_.front() != last_displayed_frame_) {
+ ++dropped_frames_;
+ }
+ frames_.pop_front();
+ }
+
+ if (audio_eos_reached) {
+ while (frames_.size() > 1) {
+ frames_.pop_back();
+ }
+ }
+}
+
SbDecodeTarget VideoRendererImpl::GetCurrentDecodeTarget(
SbMediaTime media_time,
bool audio_eos_reached) {
- SB_UNREFERENCED_PARAMETER(media_time);
- SB_UNREFERENCED_PARAMETER(audio_eos_reached);
+ {
+ ScopedLock lock(mutex_);
+ AdvanceTime(media_time, audio_eos_reached);
+ }
+
if (decoder_) {
return decoder_->GetCurrentDecodeTarget();
} else {
diff --git a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
index 1dfdad6..675dea8 100644
--- a/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
+++ b/src/starboard/shared/starboard/player/filter/video_renderer_impl_internal.h
@@ -74,6 +74,9 @@
// no longer accept more data.
static const size_t kMaxCachedFrames = 12;
+ // Advances the clock, potentially dropping any expired frames.
+ void AdvanceTime(SbMediaTime media_time, bool audio_eos_reached);
+
// VideoDecoder::Host method.
void OnDecoderStatusUpdate(VideoDecoder::Status status,
const scoped_refptr<VideoFrame>& frame)
diff --git a/src/starboard/shared/uwp/analog_thumbstick_input.cc b/src/starboard/shared/uwp/analog_thumbstick_input.cc
new file mode 100644
index 0000000..e4ab130
--- /dev/null
+++ b/src/starboard/shared/uwp/analog_thumbstick_input.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017 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/shared/uwp/analog_thumbstick_input.h"
+
+#include <Windows.Gaming.Input.h>
+#include <algorithm>
+
+#include "starboard/log.h"
+#include "starboard/shared/win32/error_utils.h"
+#include "starboard/types.h"
+
+#pragma comment(lib, "xinput9_1_0.lib")
+
+using Windows::Foundation::Collections::IVectorView;
+using Windows::Gaming::Input::Gamepad;
+using Windows::Gaming::Input::GamepadReading;
+using Windows::Gaming::Input::RawGameController;
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+namespace {
+
+const int kMaxPlayerCounter = 4;
+const float kDeadZoneThreshold = .24f;
+
+float ApplyLinearDeadZone(float value, float maxValue, float deadZoneSize) {
+ if (value < -deadZoneSize) {
+ // Increase negative values to remove the deadzone discontinuity.
+ value += deadZoneSize;
+ } else if (value > deadZoneSize) {
+ // Decrease positive values to remove the deadzone discontinuity.
+ value -= deadZoneSize;
+ } else {
+ // Values inside the deadzone come out zero.
+ return 0;
+ }
+
+ // Scale into 0-1 range.
+ float scaledValue = value / (maxValue - deadZoneSize);
+ return std::max(-1.f, std::min(scaledValue, 1.f));
+}
+
+void ApplyStickDeadZone(float x,
+ float y,
+ float max_value,
+ float dead_zone_size,
+ float* result_x,
+ float* result_y) {
+ *result_x = ApplyLinearDeadZone(x, max_value, dead_zone_size);
+ *result_y = ApplyLinearDeadZone(y, max_value, dead_zone_size);
+}
+
+ThumbSticks ReadThumbStick(Gamepad ^ controller) {
+ ThumbSticks output;
+ GamepadReading reading = controller->GetCurrentReading();
+
+ ApplyStickDeadZone(static_cast<float>(reading.LeftThumbstickX),
+ static_cast<float>(reading.LeftThumbstickY), 1.f,
+ kDeadZoneThreshold, &output.left_x, &output.left_y);
+
+ ApplyStickDeadZone(static_cast<float>(reading.RightThumbstickX),
+ static_cast<float>(reading.RightThumbstickY), 1.f,
+ kDeadZoneThreshold, &output.right_x, &output.right_y);
+ return output;
+}
+} // namespace
+
+void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination) {
+ destination->erase(destination->begin(), destination->end());
+
+ // This profiled to an average time of 33us to execute.
+ IVectorView<Gamepad ^> ^ gamepads = Gamepad::Gamepads;
+
+ // This profiled to take on average 9us of time to read controller state.
+ const uint32_t n = gamepads->Size;
+ for (uint32_t i = 0; i < n; ++i) {
+ Gamepad ^ gamepad = gamepads->GetAt(i);
+ ThumbSticks thumb_stick = ReadThumbStick(gamepad);
+ destination->push_back(thumb_stick);
+ }
+}
+
+} // namespace uwp
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/uwp/analog_thumbstick_input.h b/src/starboard/shared/uwp/analog_thumbstick_input.h
new file mode 100644
index 0000000..490bc23
--- /dev/null
+++ b/src/starboard/shared/uwp/analog_thumbstick_input.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_
+#define STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_
+
+#include <vector>
+
+#include "starboard/types.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+struct ThumbSticks {
+ float left_x = 0.0f;
+ float left_y = 0.0f;
+ float right_x = 0.0f;
+ float right_y = 0.0f;
+};
+
+// Reads all connected game pads and stores the joystick states in the
+// destination vector. Note that the destination vector is unconditionally
+// cleared before being populated.
+void GetGamepadThumbSticks(std::vector<ThumbSticks>* destination);
+
+} // namespace uwp
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_H_
diff --git a/src/starboard/shared/uwp/analog_thumbstick_input_thread.cc b/src/starboard/shared/uwp/analog_thumbstick_input_thread.cc
new file mode 100644
index 0000000..6ce605a
--- /dev/null
+++ b/src/starboard/shared/uwp/analog_thumbstick_input_thread.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017 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/shared/uwp/analog_thumbstick_input_thread.h"
+
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#include "starboard/double.h"
+#include "starboard/shared/uwp/analog_thumbstick_input.h"
+#include "starboard/shared/win32/simple_thread.h"
+#include "starboard/thread.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+using starboard::shared::win32::SimpleThread;
+
+class AnalogThumbstickThread::Impl : public SimpleThread {
+ public:
+ explicit Impl(Callback* cb) : SimpleThread("AnalogGamepad"), callback_(cb) {
+ stick_is_centered_[kSbKeyGamepadLeftStickLeft] = true;
+ stick_is_centered_[kSbKeyGamepadRightStickLeft] = true;
+ stick_is_centered_[kSbKeyGamepadLeftStickUp] = true;
+ stick_is_centered_[kSbKeyGamepadRightStickUp] = true;
+
+ SimpleThread::Start();
+ }
+ ~Impl() { SimpleThread::Join(); }
+
+ void Run() override {
+ while (!join_called()) {
+ Update();
+ // 120hz to provide smooth 60fps playback.
+ SbThreadSleep(kSbTimeSecond / kPollingFrequency);
+ }
+ }
+
+ void Update() {
+ ThumbSticks thumb_state = GetCombinedThumbStickState();
+
+ FireEventIfNecessary(kSbKeyGamepadLeftStickLeft, thumb_state.left_x);
+ FireEventIfNecessary(kSbKeyGamepadLeftStickUp, thumb_state.left_y);
+ FireEventIfNecessary(kSbKeyGamepadRightStickLeft, thumb_state.right_x);
+ FireEventIfNecessary(kSbKeyGamepadRightStickUp, thumb_state.right_y);
+ }
+
+ void FireEventIfNecessary(SbKey sb_key, float value) {
+ if (value == 0.0f) {
+ if (stick_is_centered_[sb_key]) {
+ // The previous stick input is in center position, so it is not
+ // necessary to inject another center input event.
+ return;
+ }
+ stick_is_centered_[sb_key] = true;
+ } else {
+ stick_is_centered_[sb_key] = false;
+ }
+
+ SbInputVector input_vector = {0, 0};
+
+ switch (sb_key) {
+ case kSbKeyGamepadRightStickLeft:
+ case kSbKeyGamepadLeftStickLeft: {
+ input_vector.x = value;
+ break;
+ }
+ case kSbKeyGamepadRightStickUp:
+ case kSbKeyGamepadLeftStickUp: {
+ input_vector.y = -value;
+ break;
+ }
+ default: {
+ SB_NOTREACHED();
+ break;
+ }
+ }
+ callback_->OnJoystickUpdate(sb_key, input_vector);
+ }
+
+ ThumbSticks GetCombinedThumbStickState() {
+ ThumbSticks all_thumb_state;
+ GetGamepadThumbSticks(&thumb_sticks_);
+
+ for (int i = 0; i < thumb_sticks_.size(); ++i) {
+ ThumbSticks thumb_state = thumb_sticks_[i];
+
+ all_thumb_state.left_x += thumb_state.left_x;
+ all_thumb_state.left_y += thumb_state.left_y;
+ all_thumb_state.right_x += thumb_state.right_x;
+ all_thumb_state.right_y += thumb_state.right_y;
+ }
+
+ all_thumb_state.left_x = ClampToZeroOne(all_thumb_state.left_x);
+ all_thumb_state.left_y = ClampToZeroOne(all_thumb_state.left_y);
+ all_thumb_state.right_x = ClampToZeroOne(all_thumb_state.right_x);
+ all_thumb_state.right_y = ClampToZeroOne(all_thumb_state.right_y);
+
+ return all_thumb_state;
+ }
+
+ static float ClampToZeroOne(float in) {
+ return std::max(-1.0f, std::min(1.0f, in));
+ }
+ Callback* callback_;
+ std::map<SbKey, bool> stick_is_centered_;
+ std::vector<ThumbSticks> thumb_sticks_;
+};
+
+AnalogThumbstickThread::AnalogThumbstickThread(Callback* cb) {
+ impl_.reset(new Impl(cb));
+}
+
+AnalogThumbstickThread::~AnalogThumbstickThread() {
+ impl_.reset(nullptr);
+}
+
+} // namespace uwp
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/uwp/analog_thumbstick_input_thread.h b/src/starboard/shared/uwp/analog_thumbstick_input_thread.h
new file mode 100644
index 0000000..e5bbefa
--- /dev/null
+++ b/src/starboard/shared/uwp/analog_thumbstick_input_thread.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_THREAD_H_
+#define STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_THREAD_H_
+
+#include "starboard/common/scoped_ptr.h"
+#include "starboard/configuration.h"
+#include "starboard/input.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+// This class represents a thread that will poll all gamepads for
+// the analog sticks. The sticks are summed together and then
+// the callback will be invoked with the thumbstick values.
+class AnalogThumbstickThread {
+ public:
+ enum { kPollingFrequency = 120 }; // Smooth playback for 60fps.
+
+ class Callback {
+ public:
+ virtual ~Callback() {}
+ virtual void OnJoystickUpdate(SbKey key, SbInputVector position) = 0;
+ };
+
+ explicit AnalogThumbstickThread(Callback* cb);
+ ~AnalogThumbstickThread();
+
+ private:
+ SB_DISALLOW_COPY_AND_ASSIGN(AnalogThumbstickThread);
+ class Impl;
+ scoped_ptr<Impl> impl_;
+};
+
+} // namespace uwp
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_UWP_ANALOG_THUMBSTICK_INPUT_THREAD_H_
diff --git a/src/starboard/shared/uwp/application_uwp.cc b/src/starboard/shared/uwp/application_uwp.cc
index 2343b2a..3609033 100644
--- a/src/starboard/shared/uwp/application_uwp.cc
+++ b/src/starboard/shared/uwp/application_uwp.cc
@@ -25,13 +25,16 @@
#include <vector>
#include "starboard/event.h"
+#include "starboard/input.h"
#include "starboard/log.h"
#include "starboard/mutex.h"
#include "starboard/shared/starboard/application.h"
#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
#include "starboard/shared/starboard/player/video_frame_internal.h"
+#include "starboard/shared/uwp/analog_thumbstick_input_thread.h"
#include "starboard/shared/uwp/async_utils.h"
#include "starboard/shared/uwp/window_internal.h"
+#include "starboard/shared/win32/log_file_impl.h"
#include "starboard/shared/win32/thread_private.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/string.h"
@@ -91,9 +94,20 @@
const int kWinSockVersionMinor = 2;
const char kDialParamPrefix[] = "cobalt-dial:?";
+const char kLogPathSwitch[] = "xb1_log_file";
int main_return_value = 0;
+int MakeDeviceId() {
+ // TODO: Devices MIGHT have colliding hashcodes. Some other unique int
+ // ID generation tool would be better.
+ using Windows::Security::ExchangeActiveSyncProvisioning::
+ EasClientDeviceInformation;
+ auto device_information = ref new EasClientDeviceInformation();
+ Platform::String ^ device_id_string = device_information->Id.ToString();
+ return device_id_string->GetHashCode();
+}
+
#if defined(ENABLE_DEBUG_COMMAND_LINE_SWITCHES)
// Parses a starboard: URI scheme by splitting args at ';' boundaries.
@@ -149,6 +163,16 @@
return std::equal(substring.rbegin(), substring.rend(), full_string.rbegin());
}
+std::string GetBinaryName() {
+ std::string full_binary_path = GetArgvZero();
+ std::string::size_type index = full_binary_path.rfind(SB_FILE_SEP_CHAR);
+ if (index == std::string::npos) {
+ return full_binary_path;
+ }
+
+ return full_binary_path.substr(index + 1);
+}
+
} // namespace
// Note that this is a "struct" and not a "class" because
@@ -274,7 +298,7 @@
virtual void Uninitialize() { SbAudioSinkPrivate::TearDown(); }
void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {
- SB_DLOG(INFO) << "Suspending";
+ SB_DLOG(INFO) << "Suspending application.";
// Note if we dispatch "suspend" here before pause, application.cc
// will inject the "pause" which will cause us to go async which
// will cause us to not have completed the suspend operation before
@@ -380,6 +404,17 @@
ApplicationUwp::Get()->SetCommandLine(
static_cast<int>(argv_.size()), argv_.data());
}
+
+ ApplicationUwp* application_uwp = ApplicationUwp::Get();
+ CommandLine* command_line =
+ ::starboard::shared::uwp::GetCommandLinePointer(application_uwp);
+ if (command_line->HasSwitch(kLogPathSwitch)) {
+ std::string switch_val = command_line->GetSwitchValue(kLogPathSwitch);
+ sbwin32::OpenLogInCacheDirectory(switch_val.c_str(),
+ kSbFileCreateAlways);
+ }
+ SB_LOG(INFO) << "Starting " << GetBinaryName();
+
CoreWindow::GetForCurrentThread()->Activate();
// Call DispatchStart async so the UWP system thinks we're activated.
// Some tools seem to want the application to be activated before
@@ -456,7 +491,7 @@
// If an argv[0] is required, fill it in with the result of
// GetModuleFileName()
std::string GetArgvZero() {
- const size_t kMaxModuleNameSize = 256;
+ const size_t kMaxModuleNameSize = SB_FILE_MAX_NAME;
wchar_t buffer[kMaxModuleNameSize];
DWORD result = GetModuleFileName(NULL, buffer, kMaxModuleNameSize);
std::string arg;
@@ -469,9 +504,15 @@
}
ApplicationUwp::ApplicationUwp()
- : window_(kSbWindowInvalid), localized_strings_(SbSystemGetLocaleId()) {}
+ : window_(kSbWindowInvalid),
+ localized_strings_(SbSystemGetLocaleId()),
+ device_id_(MakeDeviceId()) {
+ analog_thumbstick_thread_.reset(new AnalogThumbstickThread(this));
+}
-ApplicationUwp::~ApplicationUwp() {}
+ApplicationUwp::~ApplicationUwp() {
+ analog_thumbstick_thread_.reset(nullptr);
+}
void ApplicationUwp::Initialize() {}
@@ -595,6 +636,42 @@
SB_NOTIMPLEMENTED();
return 0;
}
+
+void ApplicationUwp::OnJoystickUpdate(SbKey key, SbInputVector input_vector) {
+ scoped_ptr<SbInputData> data(new SbInputData());
+ SbMemorySet(data.get(), 0, sizeof(*data));
+ data->window = window_;
+ data->type = kSbInputEventTypeMove;
+ data->device_type = kSbInputDeviceTypeGamepad;
+ data->device_id = device_id();
+ data->key = key;
+ data->character = 0;
+
+ data->key_modifiers = kSbKeyModifiersNone;
+ data->position = input_vector;
+
+ SbKeyLocation key_location = kSbKeyLocationUnspecified;
+ switch (key) {
+ case kSbKeyGamepadLeftStickLeft:
+ case kSbKeyGamepadLeftStickUp: {
+ key_location = kSbKeyLocationLeft;
+ break;
+ }
+ case kSbKeyGamepadRightStickLeft:
+ case kSbKeyGamepadRightStickUp: {
+ key_location = kSbKeyLocationRight;
+ }
+ default: {
+ SB_NOTREACHED();
+ break;
+ }
+ }
+
+ data->key_location = key_location;
+ Inject(new Event(kSbEventTypeInput, data.release(),
+ &Application::DeleteDestructor<SbInputData>));
+}
+
SbSystemPlatformError ApplicationUwp::OnSbSystemRaisePlatformError(
SbSystemPlatformErrorType type,
SbSystemPlatformErrorCallback callback,
diff --git a/src/starboard/shared/uwp/application_uwp.h b/src/starboard/shared/uwp/application_uwp.h
index 3ded30a..f961b79 100644
--- a/src/starboard/shared/uwp/application_uwp.h
+++ b/src/starboard/shared/uwp/application_uwp.h
@@ -1,145 +1,164 @@
-// Copyright 2017 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.
-
-#ifndef STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
-#define STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
-
-#include <agile.h>
-#include <string>
-#include <unordered_map>
-
-#include "starboard/configuration.h"
-#include "starboard/mutex.h"
-#include "starboard/shared/internal_only.h"
-#include "starboard/shared/starboard/application.h"
-#include "starboard/shared/starboard/command_line.h"
-#include "starboard/shared/starboard/localized_strings.h"
-#include "starboard/types.h"
-#include "starboard/window.h"
-
-namespace starboard {
-namespace shared {
-namespace uwp {
-
-using Windows::Media::Protection::HdcpSession;
-
-// Returns win32's GetModuleFileName(). For cases where we'd like an argv[0].
-std::string GetArgvZero();
-
-class ApplicationUwp : public shared::starboard::Application {
- public:
- ApplicationUwp();
- ~ApplicationUwp() SB_OVERRIDE;
-
- static ApplicationUwp* Get() {
- return static_cast<ApplicationUwp*>(shared::starboard::Application::Get());
- }
-
- SbWindow CreateWindowForUWP(const SbWindowOptions* options);
-
- bool DestroyWindow(SbWindow window);
-
- void DispatchStart() {
- shared::starboard::Application::DispatchStart();
- }
-
- // public for IFrameworkView subclass
- void SetCommandLine(int argc, const char** argv) {
- shared::starboard::Application::SetCommandLine(argc, argv);
- }
-
- // public for IFrameworkView subclass
- bool DispatchAndDelete(Application::Event* event) {
- return shared::starboard::Application::DispatchAndDelete(event);
- }
-
- Platform::Agile<Windows::UI::Core::CoreWindow> GetCoreWindow() const {
- return core_window_;
- }
-
- // public for IFrameworkView subclass
- void SetCoreWindow(Windows::UI::Core::CoreWindow^ window) {
- core_window_ = window;
- }
-
- void OnKeyEvent(Windows::UI::Core::CoreWindow^ sender,
- Windows::UI::Core::KeyEventArgs^ args, bool up);
-
- void Inject(Event* event) SB_OVERRIDE;
-
- void SetStartLink(const char* link) SB_OVERRIDE {
- shared::starboard::Application::SetStartLink(link);
- }
-
- SbSystemPlatformError OnSbSystemRaisePlatformError(
- SbSystemPlatformErrorType type,
- SbSystemPlatformErrorCallback callback,
- void* user_data);
-
- void OnSbSystemClearPlatformError(SbSystemPlatformError handle);
-
- // Schedules a lambda to run on the main thread and returns immediately.
- template<typename T>
- void RunInMainThreadAsync(const T& lambda) {
- core_window_->Dispatcher->RunAsync(
- CoreDispatcherPriority::Normal,
- ref new DispatchedHandler(lambda));
- }
-
- Platform::String^ GetString(const char* id, const char* fallback) const;
-
- bool IsHdcpOn();
- // Returns true on success.
- bool TurnOnHdcp();
- // Returns true on success.
- bool TurnOffHdcp();
-
- private:
- // --- Application overrides ---
- bool IsStartImmediate() SB_OVERRIDE { return false; }
- void Initialize() SB_OVERRIDE;
- void Teardown() SB_OVERRIDE;
- Event* GetNextEvent() SB_OVERRIDE;
- bool DispatchNextEvent() SB_OVERRIDE;
- void InjectTimedEvent(TimedEvent* timed_event) SB_OVERRIDE;
- void CancelTimedEvent(SbEventId event_id) SB_OVERRIDE;
- TimedEvent* GetNextDueTimedEvent() SB_OVERRIDE;
- SbTimeMonotonic GetNextTimedEventTargetTime() SB_OVERRIDE;
-
- // These two functions should only be called while holding
- // |hdcp_session_mutex_|.
- Windows::Media::Protection::HdcpSession^ GetHdcpSession();
- void ResetHdcpSession();
-
- // The single open window, if any.
- SbWindow window_;
- Platform::Agile<Windows::UI::Core::CoreWindow> core_window_;
-
- shared::starboard::LocalizedStrings localized_strings_;
-
- Mutex mutex_;
- // |timer_event_map_| is locked by |mutex_|.
- std::unordered_map<SbEventId, Windows::System::Threading::ThreadPoolTimer^>
- timer_event_map_;
-
- // |hdcp_session_| is locked by |hdcp_session_mutex_|.
- Mutex hdcp_session_mutex_;
- Windows::Media::Protection::HdcpSession^ hdcp_session_;
-};
-
-} // namespace uwp
-} // namespace shared
-} // namespace starboard
-
-#endif // STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
+// Copyright 2017 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.
+
+#ifndef STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
+#define STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
+
+#include <agile.h>
+#include <string>
+#include <unordered_map>
+
+#include "starboard/configuration.h"
+#include "starboard/input.h"
+#include "starboard/key.h"
+#include "starboard/mutex.h"
+#include "starboard/shared/internal_only.h"
+#include "starboard/shared/starboard/application.h"
+#include "starboard/shared/starboard/command_line.h"
+#include "starboard/shared/starboard/localized_strings.h"
+#include "starboard/shared/uwp/analog_thumbstick_input_thread.h"
+#include "starboard/types.h"
+#include "starboard/window.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+using Windows::Media::Protection::HdcpSession;
+
+// Returns win32's GetModuleFileName(). For cases where we'd like an argv[0].
+std::string GetArgvZero();
+
+// Including <agile.h>, will eventually include <windows.h>, which includes
+// C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\processenv.h,
+// line 164 in processenv.h redefines GetCommandLine to GetCommandLineW if
+// UNICODE is defined.
+// This function was added so that it could be used as a work around when
+// GetCommandLine() needed to be called.
+starboard::CommandLine* GetCommandLinePointer(starboard::Application* app);
+
+class ApplicationUwp : public shared::starboard::Application,
+ private AnalogThumbstickThread::Callback {
+ public:
+ ApplicationUwp();
+ ~ApplicationUwp() SB_OVERRIDE;
+
+ static ApplicationUwp* Get() {
+ return static_cast<ApplicationUwp*>(shared::starboard::Application::Get());
+ }
+
+ SbWindow CreateWindowForUWP(const SbWindowOptions* options);
+
+ bool DestroyWindow(SbWindow window);
+
+ void DispatchStart() {
+ shared::starboard::Application::DispatchStart();
+ }
+
+ // public for IFrameworkView subclass
+ void SetCommandLine(int argc, const char** argv) {
+ shared::starboard::Application::SetCommandLine(argc, argv);
+ }
+
+ // public for IFrameworkView subclass
+ bool DispatchAndDelete(Application::Event* event) {
+ return shared::starboard::Application::DispatchAndDelete(event);
+ }
+
+ Platform::Agile<Windows::UI::Core::CoreWindow> GetCoreWindow() const {
+ return core_window_;
+ }
+
+ // public for IFrameworkView subclass
+ void SetCoreWindow(Windows::UI::Core::CoreWindow^ window) {
+ core_window_ = window;
+ }
+
+ void OnKeyEvent(Windows::UI::Core::CoreWindow^ sender,
+ Windows::UI::Core::KeyEventArgs^ args, bool up);
+
+ void Inject(Event* event) SB_OVERRIDE;
+
+ void SetStartLink(const char* link) SB_OVERRIDE {
+ shared::starboard::Application::SetStartLink(link);
+ }
+
+ SbSystemPlatformError OnSbSystemRaisePlatformError(
+ SbSystemPlatformErrorType type,
+ SbSystemPlatformErrorCallback callback,
+ void* user_data);
+
+ void OnSbSystemClearPlatformError(SbSystemPlatformError handle);
+
+ // Schedules a lambda to run on the main thread and returns immediately.
+ template<typename T>
+ void RunInMainThreadAsync(const T& lambda) {
+ core_window_->Dispatcher->RunAsync(
+ CoreDispatcherPriority::Normal,
+ ref new DispatchedHandler(lambda));
+ }
+
+ Platform::String^ GetString(const char* id, const char* fallback) const;
+
+ bool IsHdcpOn();
+ // Returns true on success.
+ bool TurnOnHdcp();
+ // Returns true on success.
+ bool TurnOffHdcp();
+
+ private:
+ // --- Application overrides ---
+ bool IsStartImmediate() SB_OVERRIDE { return false; }
+ void Initialize() SB_OVERRIDE;
+ void Teardown() SB_OVERRIDE;
+ Event* GetNextEvent() SB_OVERRIDE;
+ bool DispatchNextEvent() SB_OVERRIDE;
+ void InjectTimedEvent(TimedEvent* timed_event) SB_OVERRIDE;
+ void CancelTimedEvent(SbEventId event_id) SB_OVERRIDE;
+ TimedEvent* GetNextDueTimedEvent() SB_OVERRIDE;
+ SbTimeMonotonic GetNextTimedEventTargetTime() SB_OVERRIDE;
+
+ int device_id() const { return device_id_; }
+ void OnJoystickUpdate(SbKey key, SbInputVector value) SB_OVERRIDE;
+
+ // These two functions should only be called while holding
+ // |hdcp_session_mutex_|.
+ Windows::Media::Protection::HdcpSession^ GetHdcpSession();
+ void ResetHdcpSession();
+
+ // The single open window, if any.
+ SbWindow window_;
+ Platform::Agile<Windows::UI::Core::CoreWindow> core_window_;
+
+ shared::starboard::LocalizedStrings localized_strings_;
+
+ Mutex mutex_;
+ // |timer_event_map_| is locked by |mutex_|.
+ std::unordered_map<SbEventId, Windows::System::Threading::ThreadPoolTimer^>
+ timer_event_map_;
+
+ int device_id_;
+
+ // |hdcp_session_| is locked by |hdcp_session_mutex_|.
+ Mutex hdcp_session_mutex_;
+ Windows::Media::Protection::HdcpSession^ hdcp_session_;
+
+ scoped_ptr<AnalogThumbstickThread> analog_thumbstick_thread_;
+};
+
+} // namespace uwp
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_UWP_APPLICATION_UWP_H_
\ No newline at end of file
diff --git a/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc b/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc
new file mode 100644
index 0000000..669e6a3
--- /dev/null
+++ b/src/starboard/shared/uwp/application_uwp_get_commandline_pointer.cc
@@ -0,0 +1,28 @@
+// Copyright 2017 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/shared/starboard/application.h"
+#include "starboard/shared/starboard/command_line.h"
+
+namespace starboard {
+namespace shared {
+namespace uwp {
+
+starboard::CommandLine* GetCommandLinePointer(starboard::Application* app) {
+ return app->GetCommandLine();
+}
+
+} // namespace uwp
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/uwp/application_uwp_key_event.cc b/src/starboard/shared/uwp/application_uwp_key_event.cc
index 73b7d27..cfe7c16 100644
--- a/src/starboard/shared/uwp/application_uwp_key_event.cc
+++ b/src/starboard/shared/uwp/application_uwp_key_event.cc
@@ -21,8 +21,6 @@
using Windows::UI::Core::CoreWindow;
using Windows::UI::Core::KeyEventArgs;
using Windows::UI::Core::CoreVirtualKeyStates;
-using Windows::Security::ExchangeActiveSyncProvisioning::
- EasClientDeviceInformation;
using Windows::System::VirtualKey;
namespace {
@@ -255,11 +253,7 @@
data->window = window_;
data->device_type = kSbInputDeviceTypeKeyboard;
- // TODO: Devices might have colliding hashcodes. Some other unique int
- // ID generation tool would be better.
- auto device_information = ref new EasClientDeviceInformation();
- Platform::String^ device_id_string = device_information->Id.ToString();
- data->device_id = device_id_string->GetHashCode();
+ data->device_id = device_id();
data->key = VirtualKeyToSbKey(args->VirtualKey);
if (up) {
diff --git a/src/starboard/shared/uwp/starboard_platform.gypi b/src/starboard/shared/uwp/starboard_platform.gypi
index 8d082dc..bb3a5d5 100644
--- a/src/starboard/shared/uwp/starboard_platform.gypi
+++ b/src/starboard/shared/uwp/starboard_platform.gypi
@@ -14,7 +14,12 @@
{
'variables': {
'starboard_platform_dependent_files': [
+ 'analog_thumbstick_input.cc',
+ 'analog_thumbstick_input.h',
+ 'analog_thumbstick_input_thread.cc',
+ 'analog_thumbstick_input_thread.h',
'application_uwp_key_event.cc',
+ 'application_uwp_get_commandline_pointer.cc',
'application_uwp.cc',
'application_uwp.h',
'async_utils.h',
diff --git a/src/starboard/shared/win32/gyp_configuration.py b/src/starboard/shared/win32/gyp_configuration.py
index 93f92f1..616a9c0 100644
--- a/src/starboard/shared/win32/gyp_configuration.py
+++ b/src/starboard/shared/win32/gyp_configuration.py
@@ -18,6 +18,7 @@
import config.starboard
from starboard.tools.paths import STARBOARD_ROOT
+import starboard.tools.testing.test_filter as test_filter
import sdk_configuration
@@ -87,3 +88,39 @@
os.path.join(STARBOARD_ROOT, 'shared', 'msvc', 'uwp'))
from msvc_toolchain import MSVCUWPToolchain # pylint: disable=g-import-not-at-top,g-bad-import-order
return MSVCUWPToolchain()
+
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return [
+ # Fails on JSC.
+ test_filter.TestFilter(
+ 'bindings_test', ('EvaluateScriptTest.ThreeArguments')),
+ test_filter.TestFilter(
+ 'bindings_test', ('GarbageCollectionTest.*')),
+
+ test_filter.TestFilter('nplb', test_filter.FILTER_ALL),
+ test_filter.TestFilter('poem_unittests', test_filter.FILTER_ALL),
+
+ # The Windows platform uses D3D9 which doesn't let you create a D3D
+ # device without a display, causing these unit tests to erroneously
+ # fail on the buildbots, so they are disabled for Windows only.
+ test_filter.TestFilter('layout_tests', test_filter.FILTER_ALL),
+ test_filter.TestFilter('renderer_test', test_filter.FILTER_ALL),
+
+ # No network on Windows, yet.
+ test_filter.TestFilter('web_platform_tests', test_filter.FILTER_ALL),
+ test_filter.TestFilter('net_unittests', test_filter.FILTER_ALL),
+
+ test_filter.TestFilter('starboard_platform_tests',
+ test_filter.FILTER_ALL),
+ test_filter.TestFilter('nplb_blitter_pixel_tests',
+ test_filter.FILTER_ALL),
+ test_filter.TestFilter('webdriver_test',
+ test_filter.FILTER_ALL)
+
+ ]
+
diff --git a/src/starboard/shared/win32/log_file_impl.cc b/src/starboard/shared/win32/log_file_impl.cc
new file mode 100644
index 0000000..1d258ae
--- /dev/null
+++ b/src/starboard/shared/win32/log_file_impl.cc
@@ -0,0 +1,108 @@
+// Copyright 2017 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/shared/win32/log_file_impl.h"
+
+#include <string>
+
+#include "starboard/file.h"
+#include "starboard/memory.h"
+#include "starboard/mutex.h"
+#include "starboard/once.h"
+#include "starboard/shared/win32/file_internal.h"
+#include "starboard/string.h"
+
+namespace {
+
+SbMutex log_mutex = SB_MUTEX_INITIALIZER;
+SbFile log_file = kSbFileInvalid;
+
+} // namespace
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+void CloseLogFile() {
+ SbMutexAcquire(&log_mutex);
+
+ if (SbFileIsValid(log_file)) {
+ SbFileFlush(log_file);
+ SbFileClose(log_file);
+ log_file = kSbFileInvalid;
+ }
+
+ SbMutexRelease(&log_mutex);
+}
+
+void OpenLogInCacheDirectory(const char* log_file_name, int creation_flags) {
+ SB_DCHECK((creation_flags & kSbFileOpenAlways) ||
+ (creation_flags & kSbFileCreateAlways));
+ SB_DCHECK(SbStringGetLength(log_file_name) != 0);
+ SB_DCHECK(SbStringFindCharacter(log_file_name, SB_FILE_SEP_CHAR) == nullptr);
+ char out_path[SB_FILE_MAX_PATH + 1];
+ out_path[0] = '\0';
+
+ if (!SbSystemGetPath(kSbSystemPathCacheDirectory, out_path,
+ SB_ARRAY_SIZE_INT(out_path))) {
+ return;
+ }
+
+ const int path_size = SB_ARRAY_SIZE_INT(out_path);
+ if (SbStringConcat(out_path, SB_FILE_SEP_STRING, path_size) >= path_size) {
+ return;
+ }
+ if (SbStringConcat(out_path, log_file_name, path_size) >= path_size) {
+ return;
+ }
+
+ OpenLogFile(out_path, creation_flags);
+}
+
+void OpenLogFile(const char* path, const int creation_flags) {
+ SB_DCHECK((creation_flags & kSbFileOpenAlways) ||
+ (creation_flags & kSbFileCreateAlways));
+ CloseLogFile();
+ SB_DLOG(INFO) << "Logging to [" << path << "]";
+
+ int flags = creation_flags | kSbFileWrite;
+
+ SbMutexAcquire(&log_mutex);
+ if ((path != nullptr) && (path != '\0')) {
+ log_file = SbFileOpen(path, flags, nullptr, nullptr);
+ SB_DCHECK(SbFileIsValid(log_file));
+ }
+ SbMutexRelease(&log_mutex);
+}
+
+void WriteToLogFile(const char* text, const int text_length) {
+ if (text_length <= 0) {
+ return;
+ }
+ SbMutexAcquire(&log_mutex);
+ if (!SbFileIsValid(log_file)) {
+ SbMutexRelease(&log_mutex);
+ return;
+ }
+
+ int bytes_written = SbFileWriteAll(log_file, text, text_length);
+ SB_DCHECK(text_length == bytes_written);
+
+ SbFileFlush(log_file);
+ SbMutexRelease(&log_mutex);
+}
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
diff --git a/src/starboard/shared/win32/log_file_impl.h b/src/starboard/shared/win32/log_file_impl.h
new file mode 100644
index 0000000..2ed28b9
--- /dev/null
+++ b/src/starboard/shared/win32/log_file_impl.h
@@ -0,0 +1,50 @@
+// Copyright 2017 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.
+
+// This header provides a mechanism for multiple Android logging
+// formats to share a single log file handle.
+
+#ifndef STARBOARD_SHARED_WIN32_LOG_FILE_IMPL_H_
+#define STARBOARD_SHARED_WIN32_LOG_FILE_IMPL_H_
+
+#include "starboard/file.h"
+#include "starboard/mutex.h"
+
+namespace starboard {
+namespace shared {
+namespace win32 {
+
+// Closes the log file.
+void CloseLogFile();
+
+// Opens a file in |kSbSystemPathCacheDirectory| directory.
+// |log_file_name|: C-style string of a filename
+// |creation_flags|: Must be kSbFileCreateAlways (which will truncate the file)
+// |kSbFileOpenAlways|, which can be used to append to the file.
+void OpenLogInCacheDirectory(const char* log_file_name, int creation_flags);
+
+// Opens a file at |log_file_path| with |creation_flags|.
+// |log_file_name|: C-style string of a filename
+// |creation_flags|: Must be kSbFileCreateAlways (which will truncate the file)
+// |kSbFileOpenAlways|, which can be used to append to the file.
+void OpenLogFile(const char* log_file_path, int creation_flags);
+
+// Writes |text_length| bytes starting from |text| to the current log file.
+void WriteToLogFile(const char* text, const int text_length);
+
+} // namespace win32
+} // namespace shared
+} // namespace starboard
+
+#endif // STARBOARD_SHARED_WIN32_LOG_FILE_IMPL_H_
diff --git a/src/starboard/shared/win32/log_raw.cc b/src/starboard/shared/win32/log_raw.cc
index d33f086..2929156 100644
--- a/src/starboard/shared/win32/log_raw.cc
+++ b/src/starboard/shared/win32/log_raw.cc
@@ -17,7 +17,14 @@
#include <stdio.h>
#include <windows.h>
+#include "starboard/shared/win32/log_file_impl.h"
+#include "starboard/string.h"
+
+namespace sbwin32 = starboard::shared::win32;
+
void SbLogRaw(const char* message) {
fprintf(stderr, "%s", message);
OutputDebugStringA(message);
+ sbwin32::WriteToLogFile(
+ message, static_cast<int>(SbStringGetLength(message)));
}
diff --git a/src/starboard/shared/win32/log_raw_format.cc b/src/starboard/shared/win32/log_raw_format.cc
index 5b6c59e..39b5400 100644
--- a/src/starboard/shared/win32/log_raw_format.cc
+++ b/src/starboard/shared/win32/log_raw_format.cc
@@ -17,14 +17,19 @@
#include <stdio.h>
#include <windows.h>
+#include "starboard/shared/win32/log_file_impl.h"
+
static const int kMaxLogLineChars = 16 * 1024;
+namespace sbwin32 = starboard::shared::win32;
+
void SbLogRawFormat(const char* format, va_list arguments) {
vfprintf(stderr, format, arguments);
char log_buffer[kMaxLogLineChars];
int result = vsprintf_s(log_buffer, kMaxLogLineChars, format, arguments);
- if (result >= 0) {
+ if (result > 0) {
OutputDebugStringA(log_buffer);
+ sbwin32::WriteToLogFile(log_buffer, result);
} else {
OutputDebugStringA("[log line too long]");
}
diff --git a/src/starboard/stub/gyp_configuration.py b/src/starboard/stub/gyp_configuration.py
index 63c1c9a..70f8340 100644
--- a/src/starboard/stub/gyp_configuration.py
+++ b/src/starboard/stub/gyp_configuration.py
@@ -46,3 +46,11 @@
'CXX': self.host_compiler_environment['CXX_host'],
})
return env_variables
+
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return []
diff --git a/src/starboard/tizen/armv7l/gyp_configuration.py b/src/starboard/tizen/armv7l/gyp_configuration.py
index 3cee759..50bae01 100644
--- a/src/starboard/tizen/armv7l/gyp_configuration.py
+++ b/src/starboard/tizen/armv7l/gyp_configuration.py
@@ -48,3 +48,11 @@
'CXX_host': 'armv7l-tizen-linux-gnueabi-g++',
}
return env_variables
+
+ def GetTestFilters(self):
+ """Gets all tests to be excluded from a unit test run.
+
+ Returns:
+ A list of initialized TestFilter objects.
+ """
+ return []
diff --git a/src/starboard/win/shared/configuration_public.h b/src/starboard/win/shared/configuration_public.h
index 138ca41..44e4ac9 100644
--- a/src/starboard/win/shared/configuration_public.h
+++ b/src/starboard/win/shared/configuration_public.h
@@ -20,7 +20,7 @@
// The API version implemented by this platform. This will generally be set to
// the current value of SB_MAXIMUM_API_VERSION at the time of implementation.
-#define SB_API_VERSION 6
+#define SB_API_VERSION 7
// --- Architecture Configuration --------------------------------------------
diff --git a/src/starboard/win/shared/starboard_platform.gypi b/src/starboard/win/shared/starboard_platform.gypi
index ff78819..9302e9c 100644
--- a/src/starboard/win/shared/starboard_platform.gypi
+++ b/src/starboard/win/shared/starboard_platform.gypi
@@ -302,6 +302,8 @@
'<(DEPTH)/starboard/shared/win32/file_truncate.cc',
'<(DEPTH)/starboard/shared/win32/file_write.cc',
'<(DEPTH)/starboard/shared/win32/log.cc',
+ '<(DEPTH)/starboard/shared/win32/log_file_impl.cc',
+ '<(DEPTH)/starboard/shared/win32/log_file_impl.h',
'<(DEPTH)/starboard/shared/win32/log_flush.cc',
'<(DEPTH)/starboard/shared/win32/log_format.cc',
'<(DEPTH)/starboard/shared/win32/log_is_tty.cc',