| Index: cc/output/renderer_pixeltest.cc
 | 
| diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
 | 
| index c62ae058d00de3a93b6a68d2ecc1a2a8cbc5a1c1..d9b1be517e0422b631f38b21621174ed36532340 100644
 | 
| --- a/cc/output/renderer_pixeltest.cc
 | 
| +++ b/cc/output/renderer_pixeltest.cc
 | 
| @@ -7,6 +7,7 @@
 | 
|  #include <memory>
 | 
|  
 | 
|  #include "base/message_loop/message_loop.h"
 | 
| +#include "base/strings/string_split.h"
 | 
|  #include "cc/base/math_util.h"
 | 
|  #include "cc/output/gl_renderer.h"
 | 
|  #include "cc/quads/draw_quad.h"
 | 
| @@ -16,6 +17,7 @@
 | 
|  #include "cc/test/fake_raster_source.h"
 | 
|  #include "cc/test/fake_recording_source.h"
 | 
|  #include "cc/test/pixel_test.h"
 | 
| +#include "cc/test/test_in_process_context_provider.h"
 | 
|  #include "gpu/command_buffer/client/gles2_interface.h"
 | 
|  #include "media/base/video_frame.h"
 | 
|  #include "third_party/skia/include/core/SkColorPriv.h"
 | 
| @@ -217,72 +219,85 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
 | 
|                 video_frame->rows(media::VideoFrame::kAPlane));
 | 
|    }
 | 
|  
 | 
| -  VideoFrameExternalResources resources =
 | 
| +  VideoFrameExternalResources external_resources =
 | 
|        video_resource_updater->CreateExternalResourcesFromVideoFrame(
 | 
|            video_frame);
 | 
|  
 | 
| -  EXPECT_EQ(VideoFrameExternalResources::YUV_RESOURCE, resources.type);
 | 
| -  EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
 | 
| -            resources.mailboxes.size());
 | 
| -  EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
 | 
| -            resources.release_callbacks.size());
 | 
| -
 | 
| -  ResourceId y_resource = resource_provider->CreateResourceFromTextureMailbox(
 | 
| -      resources.mailboxes[media::VideoFrame::kYPlane],
 | 
| -      SingleReleaseCallbackImpl::Create(
 | 
| -          resources.release_callbacks[media::VideoFrame::kYPlane]));
 | 
| -  ResourceId u_resource = resource_provider->CreateResourceFromTextureMailbox(
 | 
| -      resources.mailboxes[media::VideoFrame::kUPlane],
 | 
| -      SingleReleaseCallbackImpl::Create(
 | 
| -          resources.release_callbacks[media::VideoFrame::kUPlane]));
 | 
| -  ResourceId v_resource = resource_provider->CreateResourceFromTextureMailbox(
 | 
| -      resources.mailboxes[media::VideoFrame::kVPlane],
 | 
| -      SingleReleaseCallbackImpl::Create(
 | 
| -          resources.release_callbacks[media::VideoFrame::kVPlane]));
 | 
| -  ResourceId a_resource = 0;
 | 
| -  if (with_alpha) {
 | 
| -    a_resource = resource_provider->CreateResourceFromTextureMailbox(
 | 
| -        resources.mailboxes[media::VideoFrame::kAPlane],
 | 
| -        SingleReleaseCallbackImpl::Create(
 | 
| -            resources.release_callbacks[media::VideoFrame::kAPlane]));
 | 
| +  ResourceProvider::ResourceIdArray resource_ids;
 | 
| +  resource_ids.reserve(external_resources.mailboxes.size());
 | 
| +  for (size_t i = 0; i < external_resources.mailboxes.size(); ++i) {
 | 
| +    ResourceId resource_id =
 | 
| +        resource_provider->CreateResourceFromTextureMailbox(
 | 
| +            external_resources.mailboxes[i],
 | 
| +            SingleReleaseCallbackImpl::Create(
 | 
| +                external_resources.release_callbacks[i]),
 | 
| +            external_resources.read_lock_fences_enabled);
 | 
| +    resource_ids.push_back(resource_id);
 | 
|    }
 | 
|  
 | 
| -  const gfx::Size ya_tex_size = video_frame->coded_size();
 | 
| -  const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
 | 
| -      video_frame->format(), media::VideoFrame::kUPlane,
 | 
| -      video_frame->coded_size());
 | 
| -  DCHECK(uv_tex_size == media::VideoFrame::PlaneSize(
 | 
| -                            video_frame->format(), media::VideoFrame::kVPlane,
 | 
| -                            video_frame->coded_size()));
 | 
| -  if (with_alpha) {
 | 
| -    DCHECK(ya_tex_size == media::VideoFrame::PlaneSize(
 | 
| -                              video_frame->format(), media::VideoFrame::kAPlane,
 | 
| -                              video_frame->coded_size()));
 | 
| -  }
 | 
| -
 | 
| -  gfx::RectF ya_tex_coord_rect(tex_coord_rect.x() * ya_tex_size.width(),
 | 
| -                               tex_coord_rect.y() * ya_tex_size.height(),
 | 
| -                               tex_coord_rect.width() * ya_tex_size.width(),
 | 
| -                               tex_coord_rect.height() * ya_tex_size.height());
 | 
| -  gfx::RectF uv_tex_coord_rect(tex_coord_rect.x() * uv_tex_size.width(),
 | 
| -                               tex_coord_rect.y() * uv_tex_size.height(),
 | 
| -                               tex_coord_rect.width() * uv_tex_size.width(),
 | 
| -                               tex_coord_rect.height() * uv_tex_size.height());
 | 
| -
 | 
| -  YUVVideoDrawQuad* yuv_quad =
 | 
| -      render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
 | 
| -  uint32_t bits_per_channel = 8;
 | 
| -  if (video_frame->format() == media::PIXEL_FORMAT_YUV420P10 ||
 | 
| -      video_frame->format() == media::PIXEL_FORMAT_YUV422P10 ||
 | 
| -      video_frame->format() == media::PIXEL_FORMAT_YUV444P10) {
 | 
| -    bits_per_channel = 10;
 | 
| +  switch (external_resources.type) {
 | 
| +    case VideoFrameExternalResources::YUV_RESOURCE: {
 | 
| +      EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
 | 
| +                external_resources.mailboxes.size());
 | 
| +      EXPECT_EQ(media::VideoFrame::NumPlanes(video_frame->format()),
 | 
| +                external_resources.release_callbacks.size());
 | 
| +      const gfx::Size ya_tex_size = video_frame->coded_size();
 | 
| +      const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
 | 
| +          video_frame->format(), media::VideoFrame::kUPlane,
 | 
| +          video_frame->coded_size());
 | 
| +      DCHECK(uv_tex_size ==
 | 
| +             media::VideoFrame::PlaneSize(video_frame->format(),
 | 
| +                                          media::VideoFrame::kVPlane,
 | 
| +                                          video_frame->coded_size()));
 | 
| +      if (with_alpha) {
 | 
| +        DCHECK(ya_tex_size ==
 | 
| +               media::VideoFrame::PlaneSize(video_frame->format(),
 | 
| +                                            media::VideoFrame::kAPlane,
 | 
| +                                            video_frame->coded_size()));
 | 
| +      }
 | 
| +      gfx::RectF ya_tex_coord_rect(
 | 
| +          tex_coord_rect.x() * ya_tex_size.width(),
 | 
| +          tex_coord_rect.y() * ya_tex_size.height(),
 | 
| +          tex_coord_rect.width() * ya_tex_size.width(),
 | 
| +          tex_coord_rect.height() * ya_tex_size.height());
 | 
| +      gfx::RectF uv_tex_coord_rect(
 | 
| +          tex_coord_rect.x() * uv_tex_size.width(),
 | 
| +          tex_coord_rect.y() * uv_tex_size.height(),
 | 
| +          tex_coord_rect.width() * uv_tex_size.width(),
 | 
| +          tex_coord_rect.height() * uv_tex_size.height());
 | 
| +
 | 
| +      YUVVideoDrawQuad* yuv_quad =
 | 
| +          render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
 | 
| +      yuv_quad->SetNew(
 | 
| +          shared_state, rect, opaque_rect, visible_rect, ya_tex_coord_rect,
 | 
| +          uv_tex_coord_rect, ya_tex_size, uv_tex_size, resource_ids[0],
 | 
| +          resource_ids[1],
 | 
| +          resource_ids.size() > 2 ? resource_ids[2] : resource_ids[1],
 | 
| +          resource_ids.size() > 3 ? resource_ids[3] : 0, color_space,
 | 
| +          video_color_space, external_resources.offset,
 | 
| +          external_resources.multiplier, external_resources.bits_per_channel);
 | 
| +      break;
 | 
| +    }
 | 
| +    case VideoFrameExternalResources::RGBA_RESOURCE: {
 | 
| +      EXPECT_EQ(1u, external_resources.mailboxes.size());
 | 
| +      EXPECT_EQ(1u, external_resources.release_callbacks.size());
 | 
| +      float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
 | 
| +      TextureDrawQuad* texture_quad =
 | 
| +          render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
 | 
| +      texture_quad->SetNew(shared_state, rect, opaque_rect, visible_rect,
 | 
| +                           resource_ids[0], false, tex_coord_rect.origin(),
 | 
| +                           tex_coord_rect.bottom_right(), SK_ColorTRANSPARENT,
 | 
| +                           opacity, false, false, false);
 | 
| +      break;
 | 
| +    }
 | 
| +    case VideoFrameExternalResources::NONE:
 | 
| +    case VideoFrameExternalResources::RGB_RESOURCE:
 | 
| +    case VideoFrameExternalResources::RGBA_PREMULTIPLIED_RESOURCE:
 | 
| +    case VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE:
 | 
| +    case VideoFrameExternalResources::SOFTWARE_RESOURCE:
 | 
| +      NOTREACHED();
 | 
| +      break;
 | 
|    }
 | 
| -
 | 
| -  yuv_quad->SetNew(shared_state, rect, opaque_rect, visible_rect,
 | 
| -                   ya_tex_coord_rect, uv_tex_coord_rect, ya_tex_size,
 | 
| -                   uv_tex_size, y_resource, u_resource, v_resource, a_resource,
 | 
| -                   color_space, video_color_space, 0.0f, 1.0f,
 | 
| -                   bits_per_channel);
 | 
|  }
 | 
|  
 | 
|  // Upshift video frame to 10 bit.
 | 
| @@ -343,6 +358,8 @@ void CreateTestYUVVideoDrawQuad_Striped(
 | 
|      ResourceProvider* resource_provider) {
 | 
|    scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
 | 
|        format, rect.size(), rect, rect.size(), base::TimeDelta());
 | 
| +  video_frame->metadata()->SetInteger(media::VideoFrameMetadata::COLOR_SPACE,
 | 
| +                                      media::COLOR_SPACE_JPEG);
 | 
|  
 | 
|    // YUV values representing a striped pattern, for validating texture
 | 
|    // coordinates for sampling.
 | 
| @@ -486,6 +503,7 @@ void CreateTestYUVVideoDrawQuad_Solid(
 | 
|  void CreateTestYUVVideoDrawQuad_NV12(const SharedQuadState* shared_state,
 | 
|                                       media::ColorSpace video_frame_color_space,
 | 
|                                       const gfx::ColorSpace& video_color_space,
 | 
| +                                     ResourceFormat y_format,
 | 
|                                       const gfx::RectF& tex_coord_rect,
 | 
|                                       uint8_t y,
 | 
|                                       uint8_t u,
 | 
| @@ -505,8 +523,8 @@ void CreateTestYUVVideoDrawQuad_NV12(const SharedQuadState* shared_state,
 | 
|        media::PIXEL_FORMAT_NV12, media::VideoFrame::kUVPlane, rect.size());
 | 
|  
 | 
|    ResourceId y_resource = resource_provider->CreateResource(
 | 
| -      rect.size(), ResourceProvider::TEXTURE_HINT_DEFAULT,
 | 
| -      resource_provider->YuvResourceFormat(8), gfx::ColorSpace());
 | 
| +      rect.size(), ResourceProvider::TEXTURE_HINT_DEFAULT, y_format,
 | 
| +      gfx::ColorSpace());
 | 
|    ResourceId u_resource = resource_provider->CreateResource(
 | 
|        uv_tex_size, ResourceProvider::TEXTURE_HINT_DEFAULT, RGBA_8888,
 | 
|        gfx::ColorSpace());
 | 
| @@ -1094,12 +1112,71 @@ class VideoGLRendererPixelTest : public GLRendererPixelTest {
 | 
|          output_surface_->context_provider(), resource_provider_.get()));
 | 
|    }
 | 
|  
 | 
| +  void DisableOneComponentTextures() {
 | 
| +    TestInProcessContextProvider* context_provider =
 | 
| +        GetTestInProcessContextProvider();
 | 
| +    context_provider->SetDisableOneComponentTextures(true);
 | 
| +  }
 | 
| +
 | 
|    std::unique_ptr<VideoResourceUpdater> video_resource_updater_;
 | 
| +
 | 
| + protected:
 | 
| +  TestInProcessContextProvider* GetTestInProcessContextProvider() {
 | 
| +    return static_cast<TestInProcessContextProvider*>(
 | 
| +        output_surface_->context_provider());
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +enum class HighbitTexture {
 | 
| +  Y8,
 | 
| +  RGBA_8888,
 | 
| +  LUMINANCE_F16,  // need --use-gpu-in-tests
 | 
|  };
 | 
|  
 | 
|  class VideoGLRendererPixelHiLoTest
 | 
|      : public VideoGLRendererPixelTest,
 | 
| -      public ::testing::WithParamInterface<bool> {};
 | 
| +      public ::testing::WithParamInterface<
 | 
| +          ::testing::tuple<bool, HighbitTexture>> {
 | 
| + public:
 | 
| +  void SetSupportHighbitTexture(HighbitTexture texture) {
 | 
| +    TestInProcessContextProvider* context_provider =
 | 
| +        GetTestInProcessContextProvider();
 | 
| +    switch (texture) {
 | 
| +      case HighbitTexture::Y8:
 | 
| +        context_provider->SetDisableOneComponentTextures(false);
 | 
| +        context_provider->SetSupportTextureHalfFloatLinear(false);
 | 
| +        break;
 | 
| +      case HighbitTexture::RGBA_8888:
 | 
| +        context_provider->SetDisableOneComponentTextures(true);
 | 
| +        context_provider->SetSupportTextureHalfFloatLinear(false);
 | 
| +        break;
 | 
| +      case HighbitTexture::LUMINANCE_F16:
 | 
| +        context_provider->SetDisableOneComponentTextures(false);
 | 
| +        context_provider->SetSupportTextureHalfFloatLinear(true);
 | 
| +        break;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  bool IsHalfFloatLinearSupported() {
 | 
| +    if (extensions_.empty())
 | 
| +      InitializeExtensions();
 | 
| +
 | 
| +    return extensions_.find("GL_OES_texture_half_float_linear") !=
 | 
| +           extensions_.end();
 | 
| +  }
 | 
| +
 | 
| + private:
 | 
| +  void InitializeExtensions() {
 | 
| +    std::string extensions = GetTestInProcessContextProvider()
 | 
| +                                 ->ContextGL()
 | 
| +                                 ->GetRequestableExtensionsCHROMIUM();
 | 
| +    std::vector<std::string> tokens = base::SplitString(
 | 
| +        extensions, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
 | 
| +    extensions_.insert(tokens.begin(), tokens.end());
 | 
| +  }
 | 
| +
 | 
| +  std::set<std::string> extensions_;
 | 
| +};
 | 
|  
 | 
|  TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) {
 | 
|    gfx::Rect rect(this->device_viewport_size_);
 | 
| @@ -1110,7 +1187,12 @@ TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) {
 | 
|    SharedQuadState* shared_state =
 | 
|        CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 | 
|  
 | 
| -  bool highbit = GetParam();
 | 
| +  const bool highbit = testing::get<0>(GetParam());
 | 
| +  const HighbitTexture format = testing::get<1>(GetParam());
 | 
| +  if (format == HighbitTexture::LUMINANCE_F16 && !IsHalfFloatLinearSupported())
 | 
| +    return;
 | 
| +
 | 
| +  SetSupportHighbitTexture(format);
 | 
|    CreateTestYUVVideoDrawQuad_Striped(
 | 
|        shared_state, media::PIXEL_FORMAT_YV12, false, highbit,
 | 
|        gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
 | 
| @@ -1119,10 +1201,19 @@ TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) {
 | 
|    RenderPassList pass_list;
 | 
|    pass_list.push_back(std::move(pass));
 | 
|  
 | 
| -  EXPECT_TRUE(
 | 
| -      this->RunPixelTest(&pass_list,
 | 
| -                         base::FilePath(FILE_PATH_LITERAL("yuv_stripes.png")),
 | 
| -                         FuzzyPixelOffByOneComparator(true)));
 | 
| +  base::FilePath file_path =
 | 
| +      base::FilePath(FILE_PATH_LITERAL("yuv_stripes.png"));
 | 
| +  // TODO(dshwang): investigate why results per configuraion are so different.
 | 
| +  // crbug.com/622133
 | 
| +  if (format == HighbitTexture::RGBA_8888) {
 | 
| +    // Color space is so different, because this path doesn't respect video
 | 
| +    // color profile.
 | 
| +    file_path = base::FilePath(FILE_PATH_LITERAL("yuv_stripes_rgba.png"));
 | 
| +  }
 | 
| +  EXPECT_TRUE(this->RunPixelTest(
 | 
| +      &pass_list, file_path,
 | 
| +      // All pixels can be off by two, but any more than that is an error.
 | 
| +      FuzzyPixelComparator(true, 100.f, 0.f, 2.f, 2, 0)));
 | 
|  }
 | 
|  
 | 
|  TEST_P(VideoGLRendererPixelHiLoTest, ClippedYUVRect) {
 | 
| @@ -1136,7 +1227,12 @@ TEST_P(VideoGLRendererPixelHiLoTest, ClippedYUVRect) {
 | 
|    SharedQuadState* shared_state =
 | 
|        CreateTestSharedQuadState(gfx::Transform(), viewport, pass.get());
 | 
|  
 | 
| -  bool highbit = GetParam();
 | 
| +  const bool highbit = testing::get<0>(GetParam());
 | 
| +  const HighbitTexture format = testing::get<1>(GetParam());
 | 
| +  if (format == HighbitTexture::LUMINANCE_F16 && !IsHalfFloatLinearSupported())
 | 
| +    return;
 | 
| +
 | 
| +  SetSupportHighbitTexture(format);
 | 
|    CreateTestYUVVideoDrawQuad_Striped(
 | 
|        shared_state, media::PIXEL_FORMAT_YV12, false, highbit,
 | 
|        gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
 | 
| @@ -1145,9 +1241,16 @@ TEST_P(VideoGLRendererPixelHiLoTest, ClippedYUVRect) {
 | 
|    RenderPassList pass_list;
 | 
|    pass_list.push_back(std::move(pass));
 | 
|  
 | 
| +  base::FilePath file_path =
 | 
| +      base::FilePath(FILE_PATH_LITERAL("yuv_stripes_clipped.png"));
 | 
| +  if (format == HighbitTexture::RGBA_8888) {
 | 
| +    file_path =
 | 
| +        base::FilePath(FILE_PATH_LITERAL("yuv_stripes_clipped_rgba.png"));
 | 
| +  }
 | 
|    EXPECT_TRUE(this->RunPixelTest(
 | 
| -      &pass_list, base::FilePath(FILE_PATH_LITERAL("yuv_stripes_clipped.png")),
 | 
| -      FuzzyPixelOffByOneComparator(true)));
 | 
| +      &pass_list, file_path,
 | 
| +      // All pixels can be off by two, but any more than that is an error.
 | 
| +      FuzzyPixelComparator(true, 100.f, 0.f, 2.f, 2, 0)));
 | 
|  }
 | 
|  
 | 
|  TEST_F(VideoGLRendererPixelHiLoTest, OffsetYUVRect) {
 | 
| @@ -1199,7 +1302,13 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVRectBlack) {
 | 
|  }
 | 
|  
 | 
|  // First argument (test case prefix) is intentionally left empty.
 | 
| -INSTANTIATE_TEST_CASE_P(, VideoGLRendererPixelHiLoTest, ::testing::Bool());
 | 
| +INSTANTIATE_TEST_CASE_P(
 | 
| +    ,
 | 
| +    VideoGLRendererPixelHiLoTest,
 | 
| +    ::testing::Combine(::testing::Bool(),
 | 
| +                       ::testing::Values(HighbitTexture::Y8,
 | 
| +                                         HighbitTexture::LUMINANCE_F16,
 | 
| +                                         HighbitTexture::RGBA_8888)));
 | 
|  
 | 
|  TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
 | 
|    gfx::Rect rect(this->device_viewport_size_);
 | 
| @@ -1233,11 +1342,13 @@ TEST_F(VideoGLRendererPixelTest, SimpleNV12JRect) {
 | 
|    SharedQuadState* shared_state =
 | 
|        CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
 | 
|  
 | 
| +  ResourceFormat y_format = video_resource_updater_->YuvResourceFormat(8);
 | 
| +
 | 
|    // YUV of (149,43,21) should be green (0,255,0) in RGB.
 | 
|    CreateTestYUVVideoDrawQuad_NV12(
 | 
|        shared_state, media::COLOR_SPACE_JPEG, gfx::ColorSpace::CreateJpeg(),
 | 
| -      gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(), rect, rect,
 | 
| -      resource_provider_.get());
 | 
| +      y_format, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
 | 
| +      rect, rect, resource_provider_.get());
 | 
|  
 | 
|    RenderPassList pass_list;
 | 
|    pass_list.push_back(std::move(pass));
 | 
| @@ -1267,6 +1378,18 @@ TEST_F(VideoGLRendererPixelTest, YUVAEdgeBleed) {
 | 
|                                   FuzzyPixelOffByOneComparator(true)));
 | 
|  }
 | 
|  
 | 
| +TEST_F(VideoGLRendererPixelTest, TextureQuadEdgeBleed) {
 | 
| +  // VideoResourceUpdater::CreateForSoftwarePlanes() converts YUV frame to RGBA
 | 
| +  // texture.
 | 
| +  DisableOneComponentTextures();
 | 
| +  RenderPassList pass_list;
 | 
| +  CreateEdgeBleedPass(media::PIXEL_FORMAT_YV12, media::COLOR_SPACE_JPEG,
 | 
| +                      &pass_list);
 | 
| +  EXPECT_TRUE(this->RunPixelTest(&pass_list,
 | 
| +                                 base::FilePath(FILE_PATH_LITERAL("green.png")),
 | 
| +                                 FuzzyPixelOffByOneComparator(true)));
 | 
| +}
 | 
| +
 | 
|  TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) {
 | 
|    gfx::Rect rect(this->device_viewport_size_);
 | 
|  
 | 
| 
 |