Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Side by Side Diff: gpu/ipc/service/direct_composition_surface_win.cc

Issue 2849963003: Allow putting NV12 software GMBs into overlays on windows (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | gpu/ipc/service/direct_composition_surface_win_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/ipc/service/direct_composition_surface_win.h" 5 #include "gpu/ipc/service/direct_composition_surface_win.h"
6 6
7 #include <d3d11_1.h> 7 #include <d3d11_1.h>
8 #include <dcomptypes.h> 8 #include <dcomptypes.h>
9 9
10 #include <deque> 10 #include <deque>
(...skipping 12 matching lines...) Expand all
23 #include "ui/display/display_switches.h" 23 #include "ui/display/display_switches.h"
24 #include "ui/gfx/color_space_win.h" 24 #include "ui/gfx/color_space_win.h"
25 #include "ui/gfx/geometry/size_conversions.h" 25 #include "ui/gfx/geometry/size_conversions.h"
26 #include "ui/gfx/native_widget_types.h" 26 #include "ui/gfx/native_widget_types.h"
27 #include "ui/gfx/transform.h" 27 #include "ui/gfx/transform.h"
28 #include "ui/gl/dc_renderer_layer_params.h" 28 #include "ui/gl/dc_renderer_layer_params.h"
29 #include "ui/gl/egl_util.h" 29 #include "ui/gl/egl_util.h"
30 #include "ui/gl/gl_angle_util_win.h" 30 #include "ui/gl/gl_angle_util_win.h"
31 #include "ui/gl/gl_context.h" 31 #include "ui/gl/gl_context.h"
32 #include "ui/gl/gl_image_dxgi.h" 32 #include "ui/gl/gl_image_dxgi.h"
33 #include "ui/gl/gl_image_memory.h"
33 #include "ui/gl/gl_surface_egl.h" 34 #include "ui/gl/gl_surface_egl.h"
34 #include "ui/gl/scoped_make_current.h" 35 #include "ui/gl/scoped_make_current.h"
35 36
36 #ifndef EGL_ANGLE_flexible_surface_compatibility 37 #ifndef EGL_ANGLE_flexible_surface_compatibility
37 #define EGL_ANGLE_flexible_surface_compatibility 1 38 #define EGL_ANGLE_flexible_surface_compatibility 1
38 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 39 #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
39 #endif /* EGL_ANGLE_flexible_surface_compatibility */ 40 #endif /* EGL_ANGLE_flexible_surface_compatibility */
40 41
41 #ifndef EGL_ANGLE_d3d_texture_client_buffer 42 #ifndef EGL_ANGLE_d3d_texture_client_buffer
42 #define EGL_ANGLE_d3d_texture_client_buffer 1 43 #define EGL_ANGLE_d3d_texture_client_buffer 1
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 float swap_chain_scale_x() const { return swap_chain_scale_x_; } 202 float swap_chain_scale_x() const { return swap_chain_scale_x_; }
202 float swap_chain_scale_y() const { return swap_chain_scale_y_; } 203 float swap_chain_scale_y() const { return swap_chain_scale_y_; }
203 const base::win::ScopedComPtr<IDXGISwapChain1>& swap_chain() const { 204 const base::win::ScopedComPtr<IDXGISwapChain1>& swap_chain() const {
204 return swap_chain_; 205 return swap_chain_;
205 } 206 }
206 207
207 private: 208 private:
208 using PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE = 209 using PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE =
209 HRESULT(WINAPI*)(DWORD, SECURITY_ATTRIBUTES*, HANDLE*); 210 HRESULT(WINAPI*)(DWORD, SECURITY_ATTRIBUTES*, HANDLE*);
210 211
212 bool UploadMemoryImages(gl::GLImageMemory* y_image_memory,
sunnyps1 2017/05/04 22:26:56 nit: UploadVideoImages
213 gl::GLImageMemory* uv_image_memory);
211 // Returns true if the video processor changed. 214 // Returns true if the video processor changed.
212 bool InitializeVideoProcessor(const gfx::Size& in_size, 215 bool InitializeVideoProcessor(const gfx::Size& in_size,
213 const gfx::Size& out_size); 216 const gfx::Size& out_size);
214 void ReallocateSwapChain(bool yuy2); 217 void ReallocateSwapChain(bool yuy2);
215 bool ShouldBeYUY2(); 218 bool ShouldBeYUY2();
216 219
217 DCLayerTree* surface_; 220 DCLayerTree* surface_;
218 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_; 221 PFN_DCOMPOSITION_CREATE_SURFACE_HANDLE create_surface_handle_function_;
219 222
220 gfx::Size swap_chain_size_; 223 gfx::Size swap_chain_size_;
221 gfx::Size processor_input_size_; 224 gfx::Size processor_input_size_;
222 gfx::Size processor_output_size_; 225 gfx::Size processor_output_size_;
223 bool is_yuy2_swapchain_ = false; 226 bool is_yuy2_swapchain_ = false;
224 227
225 // This is the scale from the swapchain size to the size of the contents 228 // This is the scale from the swapchain size to the size of the contents
226 // onscreen. 229 // onscreen.
227 float swap_chain_scale_x_ = 0.0f; 230 float swap_chain_scale_x_ = 0.0f;
228 float swap_chain_scale_y_ = 0.0f; 231 float swap_chain_scale_y_ = 0.0f;
229 232
230 PresentationHistory presentation_history_; 233 PresentationHistory presentation_history_;
231 bool failed_to_create_yuy2_swapchain_ = false; 234 bool failed_to_create_yuy2_swapchain_ = false;
232 int frames_since_color_space_change_ = 0; 235 int frames_since_color_space_change_ = 0;
233 236
234 // This is the GLImage that was presented in the last frame. 237 // This is the GLImage that was presented in the last frame.
235 scoped_refptr<gl::GLImageDXGI> last_gl_image_; 238 scoped_refptr<gl::GLImage> last_gl_image_;
239
240 base::win::ScopedComPtr<ID3D11Texture2D> staging_texture_;
241 gfx::Size staging_texture_size_;
236 242
237 base::win::ScopedComPtr<ID3D11Device> d3d11_device_; 243 base::win::ScopedComPtr<ID3D11Device> d3d11_device_;
238 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_; 244 base::win::ScopedComPtr<IDXGISwapChain1> swap_chain_;
239 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> out_view_; 245 base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> out_view_;
240 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_; 246 base::win::ScopedComPtr<ID3D11VideoProcessor> video_processor_;
241 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator> 247 base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>
242 video_processor_enumerator_; 248 video_processor_enumerator_;
243 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_; 249 base::win::ScopedComPtr<ID3D11VideoDevice> video_device_;
244 base::win::ScopedComPtr<ID3D11VideoContext> video_context_; 250 base::win::ScopedComPtr<ID3D11VideoContext> video_context_;
245 251
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 343
338 if (is_yuy2_swapchain_) { 344 if (is_yuy2_swapchain_) {
339 // Switch to BGRA once 3/4 of presents are composed. 345 // Switch to BGRA once 3/4 of presents are composed.
340 return composition_count < (PresentationHistory::kPresentsToStore * 3 / 4); 346 return composition_count < (PresentationHistory::kPresentsToStore * 3 / 4);
341 } else { 347 } else {
342 // Switch to YUY2 once 3/4 are using overlays (or unknown). 348 // Switch to YUY2 once 3/4 are using overlays (or unknown).
343 return composition_count < (PresentationHistory::kPresentsToStore / 4); 349 return composition_count < (PresentationHistory::kPresentsToStore / 4);
344 } 350 }
345 } 351 }
346 352
353 bool DCLayerTree::SwapChainPresenter::UploadMemoryImages(
354 gl::GLImageMemory* y_image_memory,
355 gl::GLImageMemory* uv_image_memory) {
356 gfx::Size texture_size = y_image_memory->GetSize();
357 gfx::Size uv_image_size = uv_image_memory->GetSize();
358 if (uv_image_size.height() != texture_size.height() / 2 ||
359 uv_image_size.width() != texture_size.width() / 2 ||
360 y_image_memory->format() != gfx::BufferFormat::R_8 ||
361 uv_image_memory->format() != gfx::BufferFormat::RG_88) {
362 DVLOG(ERROR) << "Invalid NV12 GLImageMemory properties.";
363 return false;
364 }
365
366 if (!staging_texture_ || (staging_texture_size_ != texture_size)) {
367 staging_texture_.Reset();
368 D3D11_TEXTURE2D_DESC desc = {};
369 desc.Width = texture_size.width();
370 desc.Height = texture_size.height();
371 desc.Format = DXGI_FORMAT_NV12;
372 desc.MipLevels = 1;
373 desc.ArraySize = 1;
374 desc.Usage = D3D11_USAGE_DYNAMIC;
375
376 // This isn't actually bound to a decoder, but dynamic textures need
377 // BindFlags to be nonzero and D3D11_BIND_DECODER also works when creating
378 // a VideoProcessorInputView.
379 desc.BindFlags = D3D11_BIND_DECODER;
380 desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
381 desc.MiscFlags = 0;
382 desc.SampleDesc.Count = 1;
383 base::win::ScopedComPtr<ID3D11Texture2D> texture;
384 HRESULT hr = d3d11_device_->CreateTexture2D(&desc, nullptr,
385 staging_texture_.Receive());
386 CHECK(SUCCEEDED(hr)) << std::hex << hr;
sunnyps1 2017/05/04 22:26:56 nit: can you write a more descriptive error messag
387 staging_texture_size_ = texture_size;
388 }
389 base::win::ScopedComPtr<ID3D11DeviceContext> context;
390 d3d11_device_->GetImmediateContext(context.Receive());
391 D3D11_MAPPED_SUBRESOURCE mapped_resource;
392 HRESULT hr = context->Map(staging_texture_.Get(), 0, D3D11_MAP_WRITE_DISCARD,
393 0, &mapped_resource);
394 CHECK(SUCCEEDED(hr)) << std::hex << hr;
sunnyps1 2017/05/04 22:26:56 nit: same here
395
396 size_t dest_stride = mapped_resource.RowPitch;
397 for (int y = 0; y < texture_size.height(); y++) {
398 const uint8_t* y_source =
399 y_image_memory->memory() + y * y_image_memory->stride();
400 uint8_t* dest =
401 reinterpret_cast<uint8_t*>(mapped_resource.pData) + dest_stride * y;
402 memcpy(dest, y_source, texture_size.width());
403 }
404
405 uint8_t* uv_dest_plane_start =
406 reinterpret_cast<uint8_t*>(mapped_resource.pData) +
407 dest_stride * texture_size.height();
408 for (int y = 0; y < texture_size.height() / 2; y++) {
sunnyps1 2017/05/04 22:26:56 nit: uv_image_size.height() instead of texture_siz
409 const uint8_t* uv_source =
410 uv_image_memory->memory() + y * uv_image_memory->stride();
411 uint8_t* dest = uv_dest_plane_start + dest_stride * y;
412 memcpy(dest, uv_source, texture_size.width());
413 }
414 context->Unmap(staging_texture_.Get(), 0);
415 return true;
416 }
417
347 void DCLayerTree::SwapChainPresenter::PresentToSwapChain( 418 void DCLayerTree::SwapChainPresenter::PresentToSwapChain(
348 const ui::DCRendererLayerParams& params) { 419 const ui::DCRendererLayerParams& params) {
349 gl::GLImageDXGI* image_dxgi = 420 gl::GLImageDXGI* image_dxgi =
350 gl::GLImageDXGI::FromGLImage(params.image[0].get()); 421 gl::GLImageDXGI::FromGLImage(params.image[0].get());
351 DCHECK(image_dxgi); 422 gl::GLImageMemory* y_image_memory = nullptr;
423 gl::GLImageMemory* uv_image_memory = nullptr;
424 if (params.image.size() >= 2) {
425 y_image_memory = gl::GLImageMemory::FromGLImage(params.image[0].get());
426 uv_image_memory = gl::GLImageMemory::FromGLImage(params.image[1].get());
427 }
428
429 if (!image_dxgi && (!y_image_memory || !uv_image_memory)) {
430 DLOG(ERROR) << "Video GLImages are missing";
431 last_gl_image_ = nullptr;
432 return;
433 }
352 434
353 // Swap chain size is the minimum of the on-screen size and the source 435 // Swap chain size is the minimum of the on-screen size and the source
354 // size so the video processor can do the minimal amount of work and 436 // size so the video processor can do the minimal amount of work and
355 // the overlay has to read the minimal amount of data. 437 // the overlay has to read the minimal amount of data.
356 // DWM is also less likely to promote a surface to an overlay if it's 438 // DWM is also less likely to promote a surface to an overlay if it's
357 // much larger than its area on-screen. 439 // much larger than its area on-screen.
358 gfx::Rect bounds_rect = params.rect; 440 gfx::Rect bounds_rect = params.rect;
359 gfx::Size ceiled_input_size = gfx::ToCeiledSize(params.contents_rect.size()); 441 gfx::Size ceiled_input_size = gfx::ToCeiledSize(params.contents_rect.size());
360 gfx::Size swap_chain_size = bounds_rect.size(); 442 gfx::Size swap_chain_size = bounds_rect.size();
361 swap_chain_size.SetToMin(ceiled_input_size); 443 swap_chain_size.SetToMin(ceiled_input_size);
362 444
363 // YUY2 surfaces must have an even width. 445 // YUY2 surfaces must have an even width.
364 if (swap_chain_size.width() % 2 == 1) 446 if (swap_chain_size.width() % 2 == 1)
365 swap_chain_size.set_width(swap_chain_size.width() + 1); 447 swap_chain_size.set_width(swap_chain_size.width() + 1);
366 448
367 InitializeVideoProcessor(ceiled_input_size, swap_chain_size); 449 InitializeVideoProcessor(ceiled_input_size, swap_chain_size);
368 450
369 bool yuy2_swapchain = ShouldBeYUY2(); 451 bool yuy2_swapchain = ShouldBeYUY2();
370 bool first_present = false; 452 bool first_present = false;
371 if (!swap_chain_ || swap_chain_size_ != swap_chain_size || 453 if (!swap_chain_ || swap_chain_size_ != swap_chain_size ||
372 ((yuy2_swapchain != is_yuy2_swapchain_) && 454 ((yuy2_swapchain != is_yuy2_swapchain_) &&
373 !failed_to_create_yuy2_swapchain_)) { 455 !failed_to_create_yuy2_swapchain_)) {
374 first_present = true; 456 first_present = true;
375 swap_chain_size_ = swap_chain_size; 457 swap_chain_size_ = swap_chain_size;
376 swap_chain_.Reset(); 458 swap_chain_.Reset();
377 ReallocateSwapChain(yuy2_swapchain); 459 ReallocateSwapChain(yuy2_swapchain);
378 } else if (last_gl_image_ == image_dxgi) { 460 } else if (last_gl_image_ == params.image[0]) {
sunnyps1 2017/05/04 22:26:56 Does this check also work for YUV? Can't UV change
379 // The swap chain is presenting the same image as last swap, which means 461 // The swap chain is presenting the same image as last swap, which means
380 // that the image was never returned to the video decoder and should have 462 // that the image was never returned to the video decoder and should have
381 // the same contents as last time. It shouldn't need to be redrawn. 463 // the same contents as last time. It shouldn't need to be redrawn.
382 return; 464 return;
383 } 465 }
384 466
385 last_gl_image_ = image_dxgi; 467 last_gl_image_ = params.image[0];
468
469 base::win::ScopedComPtr<ID3D11Texture2D> input_texture;
470 UINT input_level;
471 if (image_dxgi) {
472 input_texture = image_dxgi->texture();
473 input_level = (UINT)image_dxgi->level();
474 staging_texture_.Reset();
475 } else {
476 DCHECK(!!y_image_memory);
sunnyps1 2017/05/04 22:26:56 nit: DCHECK(y_image_memory)
477 DCHECK(!!uv_image_memory);
478 if (!UploadMemoryImages(y_image_memory, uv_image_memory))
479 return;
480 DCHECK(staging_texture_);
481 input_texture = staging_texture_;
482 input_level = 0;
483 }
386 484
387 if (!out_view_) { 485 if (!out_view_) {
388 base::win::ScopedComPtr<ID3D11Texture2D> texture; 486 base::win::ScopedComPtr<ID3D11Texture2D> texture;
389 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive())); 487 swap_chain_->GetBuffer(0, IID_PPV_ARGS(texture.Receive()));
390 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {}; 488 D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC out_desc = {};
391 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D; 489 out_desc.ViewDimension = D3D11_VPOV_DIMENSION_TEXTURE2D;
392 out_desc.Texture2D.MipSlice = 0; 490 out_desc.Texture2D.MipSlice = 0;
393 HRESULT hr = video_device_->CreateVideoProcessorOutputView( 491 HRESULT hr = video_device_->CreateVideoProcessorOutputView(
394 texture.Get(), video_processor_enumerator_.Get(), &out_desc, 492 texture.Get(), video_processor_enumerator_.Get(), &out_desc,
395 out_view_.Receive()); 493 out_view_.Receive());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = 530 D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space =
433 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); 531 gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space);
434 video_context_->VideoProcessorSetOutputColorSpace(video_processor_.Get(), 532 video_context_->VideoProcessorSetOutputColorSpace(video_processor_.Get(),
435 &d3d11_color_space); 533 &d3d11_color_space);
436 } 534 }
437 } 535 }
438 536
439 { 537 {
440 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; 538 D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {};
441 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; 539 in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D;
442 in_desc.Texture2D.ArraySlice = (UINT)image_dxgi->level(); 540 in_desc.Texture2D.ArraySlice = input_level;
443 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view; 541 base::win::ScopedComPtr<ID3D11VideoProcessorInputView> in_view;
444 HRESULT hr = video_device_->CreateVideoProcessorInputView( 542 HRESULT hr = video_device_->CreateVideoProcessorInputView(
445 image_dxgi->texture().Get(), video_processor_enumerator_.Get(), 543 input_texture.Get(), video_processor_enumerator_.Get(), &in_desc,
446 &in_desc, in_view.Receive()); 544 in_view.Receive());
447 CHECK(SUCCEEDED(hr)); 545 CHECK(SUCCEEDED(hr));
448 546
449 D3D11_VIDEO_PROCESSOR_STREAM stream = {}; 547 D3D11_VIDEO_PROCESSOR_STREAM stream = {};
450 stream.Enable = true; 548 stream.Enable = true;
451 stream.OutputIndex = 0; 549 stream.OutputIndex = 0;
452 stream.InputFrameOrField = 0; 550 stream.InputFrameOrField = 0;
453 stream.PastFrames = 0; 551 stream.PastFrames = 0;
454 stream.FutureFrames = 0; 552 stream.FutureFrames = 0;
455 stream.pInputSurface = in_view.Get(); 553 stream.pInputSurface = in_view.Get();
456 RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT(); 554 RECT dest_rect = gfx::Rect(swap_chain_size).ToRECT();
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 // The overall visual tree has one clip visual for every overlay (including 852 // The overall visual tree has one clip visual for every overlay (including
755 // the main plane). The clip visuals are in z_order and are all children of 853 // the main plane). The clip visuals are in z_order and are all children of
756 // a root visual. Each clip visual has a child visual that has the actual 854 // a root visual. Each clip visual has a child visual that has the actual
757 // plane content. 855 // plane content.
758 856
759 for (size_t i = 0; i < pending_overlays_.size(); i++) { 857 for (size_t i = 0; i < pending_overlays_.size(); i++) {
760 ui::DCRendererLayerParams& params = *pending_overlays_[i]; 858 ui::DCRendererLayerParams& params = *pending_overlays_[i];
761 VisualInfo* visual_info = &visual_info_[i]; 859 VisualInfo* visual_info = &visual_info_[i];
762 860
763 InitVisual(i); 861 InitVisual(i);
764 if (params.image.size() > 0 && params.image[0] && 862 if (params.image.size() >= 1 && params.image[0]) {
765 params.image[0]->GetType() == gl::GLImage::Type::DXGI_IMAGE) {
766 UpdateVisualForVideo(visual_info, params); 863 UpdateVisualForVideo(visual_info, params);
767 } else if (params.image.empty()) { 864 } else if (params.image.empty()) {
768 UpdateVisualForBackbuffer(visual_info, params); 865 UpdateVisualForBackbuffer(visual_info, params);
769 } else { 866 } else {
770 CHECK(false); 867 CHECK(false);
771 } 868 }
772 UpdateVisualClip(visual_info, params); 869 UpdateVisualClip(visual_info, params);
773 } 870 }
774 871
775 HRESULT hr = dcomp_device_->Commit(); 872 HRESULT hr = dcomp_device_->Commit();
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() { 1255 DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
1159 return child_window_.GetTaskRunnerForTesting(); 1256 return child_window_.GetTaskRunnerForTesting();
1160 } 1257 }
1161 1258
1162 base::win::ScopedComPtr<IDXGISwapChain1> 1259 base::win::ScopedComPtr<IDXGISwapChain1>
1163 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const { 1260 DirectCompositionSurfaceWin::GetLayerSwapChainForTesting(size_t index) const {
1164 return layer_tree_->GetLayerSwapChainForTesting(index); 1261 return layer_tree_->GetLayerSwapChainForTesting(index);
1165 } 1262 }
1166 1263
1167 } // namespace gpu 1264 } // namespace gpu
OLDNEW
« no previous file with comments | « no previous file | gpu/ipc/service/direct_composition_surface_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698