summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-07 08:24:51 +0000
committernick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-07 08:24:51 +0000
commit7929b6c273b2cd5e1d4158c8bad301cb58312ac1 (patch)
treeae8c692404dcf8da28034321774409fe30c96d0c
parentf9307cc1f95bbc9c65252abb79900e1dff4da07e (diff)
downloadchromium_src-7929b6c273b2cd5e1d4158c8bad301cb58312ac1.zip
chromium_src-7929b6c273b2cd5e1d4158c8bad301cb58312ac1.tar.gz
chromium_src-7929b6c273b2cd5e1d4158c8bad301cb58312ac1.tar.bz2
accelerated_surface_transformer_win: Improve readback and scaling performance
by caching temporary surfaces. This greatly improves the performance of tab capture on current-model Core i3 and Core i5 systems with Intel HD 3000/4000 graphics, and the default drivers under Win8. On these target systems as much as 15ms was spent in the ~ScopedComPtr dtor, freeing the temporary surfaces. Patch is intended to be as low-risk as possible while fixing the performance, since most of this code will go away soon when we do not care about non-Aura Windows. BUG=235502 TEST=surface_gpu_tests Review URL: https://chromiumcodereview.appspot.com/14763006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198670 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/surface/accelerated_surface_transformer_win.cc99
-rw-r--r--ui/surface/accelerated_surface_transformer_win.h30
-rw-r--r--ui/surface/accelerated_surface_transformer_win_unittest.cc34
-rw-r--r--ui/surface/accelerated_surface_win.cc22
-rw-r--r--ui/surface/d3d9_utils_win.cc72
-rw-r--r--ui/surface/d3d9_utils_win.h43
6 files changed, 188 insertions, 112 deletions
diff --git a/ui/surface/accelerated_surface_transformer_win.cc b/ui/surface/accelerated_surface_transformer_win.cc
index 9a17d1d..0706a1a 100644
--- a/ui/surface/accelerated_surface_transformer_win.cc
+++ b/ui/surface/accelerated_surface_transformer_win.cc
@@ -167,7 +167,7 @@ bool AcceleratedSurfaceTransformer::DoInit(IDirect3DDevice9* device) {
}
COMPILE_ASSERT(NUM_SHADERS == 6, must_compile_at_doinit);
- base::win::ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration;
+ ScopedComPtr<IDirect3DVertexDeclaration9> vertex_declaration;
HRESULT hr = device_->CreateVertexDeclaration(g_vertexElements,
vertex_declaration.Receive());
if (FAILED(hr))
@@ -221,6 +221,15 @@ void AcceleratedSurfaceTransformer::ReleaseAll() {
vertex_shaders_[i] = NULL;
pixel_shaders_[i] = NULL;
}
+
+ user_scratch_texture_ = NULL;
+ uv_scratch_texture_ = NULL;
+ y_scratch_surface_ = NULL;
+ u_scratch_surface_ = NULL;
+ v_scratch_surface_ = NULL;
+ for (int i = 0; i < arraysize(scaler_scratch_surfaces_); i++)
+ scaler_scratch_surfaces_[i] = NULL;
+
device_ = NULL;
}
void AcceleratedSurfaceTransformer::DetachAll() {
@@ -228,6 +237,15 @@ void AcceleratedSurfaceTransformer::DetachAll() {
vertex_shaders_[i].Detach();
pixel_shaders_[i].Detach();
}
+
+ user_scratch_texture_.Detach();
+ uv_scratch_texture_.Detach();
+ y_scratch_surface_.Detach();
+ u_scratch_surface_.Detach();
+ v_scratch_surface_.Detach();
+ for (int i = 0; i < arraysize(scaler_scratch_surfaces_); i++)
+ scaler_scratch_surfaces_[i].Detach();
+
device_.Detach();
}
@@ -314,12 +332,28 @@ void AcceleratedSurfaceTransformer::DrawScreenAlignedQuad(
}
+bool AcceleratedSurfaceTransformer::GetIntermediateTexture(
+ const gfx::Size& size,
+ IDirect3DTexture9** texture,
+ IDirect3DSurface9** texture_level_zero) {
+ if (!d3d_utils::CreateOrReuseRenderTargetTexture(device(),
+ size,
+ &user_scratch_texture_,
+ texture_level_zero))
+ return false;
+
+ *texture = ScopedComPtr<IDirect3DTexture9>(user_scratch_texture_).Detach();
+ return true;
+}
+
// Resize an RGB surface using repeated linear interpolation.
bool AcceleratedSurfaceTransformer::ResizeBilinear(
IDirect3DSurface9* src_surface,
const gfx::Rect& src_subrect,
IDirect3DSurface9* dst_surface,
const gfx::Rect& dst_rect) {
+ COMPILE_ASSERT(arraysize(scaler_scratch_surfaces_) == 2, surface_count);
+
gfx::Size src_size = src_subrect.size();
gfx::Size dst_size = dst_rect.size();
@@ -329,22 +363,19 @@ bool AcceleratedSurfaceTransformer::ResizeBilinear(
HRESULT hr = S_OK;
// Set up intermediate buffers needed for downsampling.
const int resample_count = GetResampleCount(src_subrect, dst_size);
- base::win::ScopedComPtr<IDirect3DSurface9> temp_buffer[2];
const gfx::Size half_size =
GetHalfSizeNoLessThan(src_subrect.size(), dst_size);
if (resample_count > 1) {
- TRACE_EVENT0("gpu", "CreateTemporarySurface");
- if (!d3d_utils::CreateTemporaryLockableSurface(device(),
- half_size,
- temp_buffer[0].Receive()))
+ if (!d3d_utils::CreateOrReuseLockableSurface(device(),
+ half_size,
+ &scaler_scratch_surfaces_[0]))
return false;
}
if (resample_count > 2) {
- TRACE_EVENT0("gpu", "CreateTemporarySurface");
const gfx::Size quarter_size = GetHalfSizeNoLessThan(half_size, dst_size);
- if (!d3d_utils::CreateTemporaryLockableSurface(device(),
- quarter_size,
- temp_buffer[1].Receive()))
+ if (!d3d_utils::CreateOrReuseLockableSurface(device(),
+ quarter_size,
+ &scaler_scratch_surfaces_[1]))
return false;
}
@@ -358,14 +389,14 @@ bool AcceleratedSurfaceTransformer::ResizeBilinear(
for (int i = 0; i < resample_count; ++i) {
TRACE_EVENT0("gpu", "StretchRect");
IDirect3DSurface9* read_buffer =
- (i == 0) ? src_surface : temp_buffer[read_buffer_index];
+ (i == 0) ? src_surface : scaler_scratch_surfaces_[read_buffer_index];
IDirect3DSurface9* write_buffer;
RECT write_rect;
if (i == resample_count - 1) {
write_buffer = dst_surface;
write_rect = dst_rect.ToRECT();
} else {
- write_buffer = temp_buffer[write_buffer_index];
+ write_buffer = scaler_scratch_surfaces_[write_buffer_index];
write_rect = gfx::Rect(write_size).ToRECT();
}
@@ -468,7 +499,7 @@ bool AcceleratedSurfaceTransformer::ReadByGetRenderTargetData(
int dst_num_rows,
int dst_stride) {
HRESULT hr = 0;
- base::win::ScopedComPtr<IDirect3DSurface9> system_surface;
+ ScopedComPtr<IDirect3DSurface9> system_surface;
gfx::Size src_size = d3d_utils::GetSize(gpu_surface);
// Depending on pitch and alignment, we might be able to wrap |dst| in an
@@ -525,12 +556,23 @@ bool AcceleratedSurfaceTransformer::AllocYUVBuffers(
// U and V are half the size (rounded up) of Y.
*uv_size = gfx::Size((y_size->width() + 1) / 2, (y_size->height() + 1) / 2);
- if (!d3d_utils::CreateTemporaryLockableSurface(device(), *y_size, dst_y))
+ if (!d3d_utils::CreateOrReuseLockableSurface(device(), *y_size,
+ &y_scratch_surface_)) {
return false;
- if (!d3d_utils::CreateTemporaryLockableSurface(device(), *uv_size, dst_u))
+ }
+ if (!d3d_utils::CreateOrReuseLockableSurface(device(), *uv_size,
+ &u_scratch_surface_)) {
return false;
- if (!d3d_utils::CreateTemporaryLockableSurface(device(), *uv_size, dst_v))
+ }
+ if (!d3d_utils::CreateOrReuseLockableSurface(device(), *uv_size,
+ &v_scratch_surface_)) {
return false;
+ }
+
+ *dst_y = ScopedComPtr<IDirect3DSurface9>(y_scratch_surface_).Detach();
+ *dst_u = ScopedComPtr<IDirect3DSurface9>(u_scratch_surface_).Detach();
+ *dst_v = ScopedComPtr<IDirect3DSurface9>(v_scratch_surface_).Detach();
+
return true;
}
@@ -550,12 +592,12 @@ bool AcceleratedSurfaceTransformer::TransformRGBToYV12_MRT(
// Create an intermediate surface to hold the UUVV values. This is color
// target 1 for the first pass, and texture 0 for the second pass. Its
// values are not read afterwards.
- base::win::ScopedComPtr<IDirect3DTexture9> uv_as_texture;
- base::win::ScopedComPtr<IDirect3DSurface9> uv_as_surface;
- if (!d3d_utils::CreateTemporaryRenderTargetTexture(device(),
- packed_y_size,
- uv_as_texture.Receive(),
- uv_as_surface.Receive())) {
+
+ ScopedComPtr<IDirect3DSurface9> uv_as_surface;
+ if (!d3d_utils::CreateOrReuseRenderTargetTexture(device(),
+ packed_y_size,
+ &uv_scratch_texture_,
+ uv_as_surface.Receive())) {
return false;
}
@@ -592,7 +634,7 @@ bool AcceleratedSurfaceTransformer::TransformRGBToYV12_MRT(
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
- device()->SetTexture(0, uv_as_texture);
+ device()->SetTexture(0, uv_scratch_texture_);
device()->SetRenderTarget(0, dst_u);
device()->SetRenderTarget(1, dst_v);
DrawScreenAlignedQuad(packed_y_size);
@@ -614,7 +656,7 @@ bool AcceleratedSurfaceTransformer::TransformRGBToYV12_WithoutMRT(
ScopedRenderTargetRestorer color0_restorer(device(), 0);
- base::win::ScopedComPtr<IDirect3DTexture9> scaled_src_surface;
+ ScopedComPtr<IDirect3DTexture9> scaled_src_surface;
// If scaling is requested, do it to a temporary texture. The MRT path
// gets a scale for free, so we need to support it here too (even though
@@ -622,16 +664,15 @@ bool AcceleratedSurfaceTransformer::TransformRGBToYV12_WithoutMRT(
if (d3d_utils::GetSize(src_surface) == dst_size) {
scaled_src_surface = src_surface;
} else {
- base::win::ScopedComPtr<IDirect3DSurface9> dst_level0;
- if (!d3d_utils::CreateTemporaryRenderTargetTexture(
- device(), dst_size,
- scaled_src_surface.Receive(), dst_level0.Receive())) {
+ ScopedComPtr<IDirect3DSurface9> dst_level0;
+ if (!d3d_utils::CreateOrReuseRenderTargetTexture(
+ device(), dst_size, &uv_scratch_texture_, dst_level0.Receive())) {
return false;
}
-
if (!Copy(src_surface, dst_level0, dst_size)) {
return false;
}
+ scaled_src_surface = uv_scratch_texture_;
}
// Input texture is the same for all three passes.
diff --git a/ui/surface/accelerated_surface_transformer_win.h b/ui/surface/accelerated_surface_transformer_win.h
index 9e23230..b04d0ab 100644
--- a/ui/surface/accelerated_surface_transformer_win.h
+++ b/ui/surface/accelerated_surface_transformer_win.h
@@ -51,12 +51,21 @@ class SURFACE_EXPORT AcceleratedSurfaceTransformer {
IDirect3DSurface9* dst_surface,
const gfx::Size& dst_size);
- // Draw a textured quad to a surface.
+ // Draw a textured quad to a surface.
bool Copy(
IDirect3DTexture9* src_texture,
IDirect3DSurface9* dst_surface,
const gfx::Size& dst_size);
+ // Get an intermediate buffer of a particular |size|, that can be used as the
+ // output of one transformation and the to another. The returned surface
+ // belongs to an internal cache, and is invalidated by a subsequent call to
+ // this method.
+ bool GetIntermediateTexture(
+ const gfx::Size& size,
+ IDirect3DTexture9** texture,
+ IDirect3DSurface9** texture_level_zero);
+
// Resize a surface using repeated bilinear interpolation.
bool ResizeBilinear(
IDirect3DSurface9* src_surface,
@@ -82,8 +91,9 @@ class SURFACE_EXPORT AcceleratedSurfaceTransformer {
// If |src_texture|'s dimensions do not match |dst_size|, the source will be
// bilinearly interpolated during conversion.
//
- // Returns true if successful. Caller must be certain to free the buffers
- // even if this function returns false.
+ // Returns true if successful. Caller must be certain to release the surfaces
+ // even if this function returns false. The returned surfaces belong to an
+ // internal cache, and are invalidated by a subsequent call to this method.
bool TransformRGBToYV12(
IDirect3DTexture9* src_texture,
const gfx::Size& dst_size,
@@ -159,8 +169,9 @@ class SURFACE_EXPORT AcceleratedSurfaceTransformer {
// roundings. The sizes of the buffers (in terms of ARGB pixels) are returned
// as |packed_y_size| and |packed_uv_size|.
//
- // Returns true if successful. Caller must be certain to free the buffers
- // even if this function returns false.
+ // Returns true if successful. Caller must be certain to release the surfaces
+ // even if this function returns false. The returned belong to an internal
+ // cache.
bool AllocYUVBuffers(
const gfx::Size& dst_size,
gfx::Size* packed_y_size,
@@ -199,6 +210,15 @@ class SURFACE_EXPORT AcceleratedSurfaceTransformer {
base::win::ScopedComPtr<IDirect3DDevice9> device_;
base::win::ScopedComPtr<IDirect3DVertexShader9> vertex_shaders_[NUM_SHADERS];
base::win::ScopedComPtr<IDirect3DPixelShader9> pixel_shaders_[NUM_SHADERS];
+
+ // Temporary and scratch surfaces; cached to avoid frequent reallocation.
+ base::win::ScopedComPtr<IDirect3DTexture9> user_scratch_texture_;
+ base::win::ScopedComPtr<IDirect3DTexture9> uv_scratch_texture_;
+ base::win::ScopedComPtr<IDirect3DSurface9> y_scratch_surface_;
+ base::win::ScopedComPtr<IDirect3DSurface9> u_scratch_surface_;
+ base::win::ScopedComPtr<IDirect3DSurface9> v_scratch_surface_;
+ base::win::ScopedComPtr<IDirect3DSurface9> scaler_scratch_surfaces_[2];
+
bool device_supports_multiple_render_targets_;
const BYTE* vertex_shader_sources_[NUM_SHADERS];
const BYTE* pixel_shader_sources_[NUM_SHADERS];
diff --git a/ui/surface/accelerated_surface_transformer_win_unittest.cc b/ui/surface/accelerated_surface_transformer_win_unittest.cc
index 1265e6e..fb19c66 100644
--- a/ui/surface/accelerated_surface_transformer_win_unittest.cc
+++ b/ui/surface/accelerated_surface_transformer_win_unittest.cc
@@ -349,11 +349,11 @@ bool AssertSameColor(uint8 color_a, uint8 color_b) {
set_color_error_tolerance(4);
base::win::ScopedComPtr<IDirect3DSurface9> src, dst;
- ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(
- device(), src_size, src.Receive()))
+ ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface(
+ device(), src_size, &src))
<< "Could not create src render target";
- ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(
- device(), dst_size, dst.Receive()))
+ ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface(
+ device(), dst_size, &dst))
<< "Could not create dst render target";
FillSymmetricRandomCheckerboard(src, src_size, checkerboard_size);
@@ -367,12 +367,12 @@ bool AssertSameColor(uint8 color_a, uint8 color_b) {
void CreateRandomCheckerboardTexture(
const gfx::Size& size,
int checkerboard_size,
- IDirect3DSurface9** reference_surface,
- IDirect3DTexture9** result) {
+ base::win::ScopedComPtr<IDirect3DSurface9>* reference_surface,
+ base::win::ScopedComPtr<IDirect3DTexture9>* result) {
base::win::ScopedComPtr<IDirect3DSurface9> dst;
- ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), size,
+ ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface(device(), size,
reference_surface));
- ASSERT_TRUE(d3d_utils::CreateTemporaryRenderTargetTexture(device(), size,
+ ASSERT_TRUE(d3d_utils::CreateOrReuseRenderTargetTexture(device(), size,
result, dst.Receive()));
FillRandomCheckerboard(*reference_surface, size, checkerboard_size);
ASSERT_HRESULT_SUCCEEDED(
@@ -411,8 +411,7 @@ bool AssertSameColor(uint8 color_a, uint8 color_b) {
base::win::ScopedComPtr<IDirect3DSurface9> dst, reference_pattern;
base::win::ScopedComPtr<IDirect3DTexture9> src;
- CreateRandomCheckerboardTexture(size, 1, reference_pattern.Receive(),
- src.Receive());
+ CreateRandomCheckerboardTexture(size, 1, &reference_pattern, &src);
// Alloc a slightly larger image 75% of the time, to test that the
// viewport is set properly.
@@ -420,8 +419,8 @@ bool AssertSameColor(uint8 color_a, uint8 color_b) {
gfx::Size alloc_size((size.width() + kAlign - 1) / kAlign * kAlign,
(size.height() + kAlign - 1) / kAlign * kAlign);
- ASSERT_TRUE(d3d_utils::CreateTemporaryLockableSurface(device(), alloc_size,
- dst.Receive())) << "Could not create dst render target.";
+ ASSERT_TRUE(d3d_utils::CreateOrReuseLockableSurface(device(), alloc_size,
+ &dst)) << "Could not create dst render target.";
ASSERT_TRUE(gpu_ops->CopyInverted(src, dst, size));
AssertIsInvertedCopy(size, reference_pattern, dst);
@@ -479,8 +478,8 @@ bool AssertSameColor(uint8 color_a, uint8 color_b) {
// (or maybe more pixels = more test trials). Results are usually to an
// error of 1, but we must use a tolerance of 3.
set_color_error_tolerance(3);
- CreateRandomCheckerboardTexture(
- src_size, checkerboard_size, reference.Receive(), src.Receive());
+ CreateRandomCheckerboardTexture(src_size, checkerboard_size, &reference,
+ &src);
gfx::Size packed_y_size, packed_uv_size;
@@ -523,10 +522,9 @@ bool AssertSameColor(uint8 color_a, uint8 color_b) {
// We'll call Copy to do the bilinear scaling if needed.
base::win::ScopedComPtr<IDirect3DSurface9> reference_scaled;
ASSERT_TRUE(
- d3d_utils::CreateTemporaryLockableSurface(
- device(), dst_size, reference_scaled.Receive()));
- ASSERT_TRUE(
- gpu_ops->Copy(src, reference_scaled, dst_size));
+ d3d_utils::CreateOrReuseLockableSurface(
+ device(), dst_size, &reference_scaled));
+ ASSERT_TRUE(gpu_ops->Copy(src, reference_scaled, dst_size));
BeforeLockWorkaround();
reference_rgb_scaled = ToSkBitmap(reference_scaled, false);
}
diff --git a/ui/surface/accelerated_surface_win.cc b/ui/surface/accelerated_surface_win.cc
index 1223616..03d4880 100644
--- a/ui/surface/accelerated_surface_win.cc
+++ b/ui/surface/accelerated_surface_win.cc
@@ -456,10 +456,9 @@ bool AcceleratedPresenter::DoCopyToARGB(const gfx::Rect& requested_src_subrect,
src_subrect.Intersect(gfx::Rect(back_buffer_size));
base::win::ScopedComPtr<IDirect3DSurface9> final_surface;
{
- TRACE_EVENT0("gpu", "CreateTemporaryLockableSurface");
- if (!d3d_utils::CreateTemporaryLockableSurface(present_thread_->device(),
- dst_size,
- final_surface.Receive())) {
+ if (!d3d_utils::CreateOrReuseLockableSurface(present_thread_->device(),
+ dst_size,
+ &final_surface)) {
LOG(ERROR) << "Failed to create temporary lockable surface";
return false;
}
@@ -527,17 +526,12 @@ bool AcceleratedPresenter::DoCopyToYUV(
gfx::Rect src_subrect = requested_src_subrect;
src_subrect.Intersect(gfx::Rect(back_buffer_size));
- base::win::ScopedComPtr<IDirect3DTexture9> resized_as_texture;
base::win::ScopedComPtr<IDirect3DSurface9> resized;
- {
- TRACE_EVENT0("gpu", "CreateTemporaryRenderTargetTexture");
- if (!d3d_utils::CreateTemporaryRenderTargetTexture(
- present_thread_->device(),
- dst_size,
- resized_as_texture.Receive(),
- resized.Receive())) {
- return false;
- }
+ base::win::ScopedComPtr<IDirect3DTexture9> resized_as_texture;
+ if (!gpu_ops->GetIntermediateTexture(dst_size,
+ resized_as_texture.Receive(),
+ resized.Receive())) {
+ return false;
}
// Shrink the source to fit entirely in the destination while preserving
diff --git a/ui/surface/d3d9_utils_win.cc b/ui/surface/d3d9_utils_win.cc
index b4d210b..a95ffb6 100644
--- a/ui/surface/d3d9_utils_win.cc
+++ b/ui/surface/d3d9_utils_win.cc
@@ -4,6 +4,7 @@
#include "ui/surface/d3d9_utils_win.h"
+#include "base/debug/trace_event.h"
#include "base/files/file_path.h"
#include "base/scoped_native_library.h"
#include "base/win/scoped_comptr.h"
@@ -71,6 +72,7 @@ bool OpenSharedTexture(IDirect3DDevice9* device,
int64 surface_handle,
const gfx::Size& size,
IDirect3DTexture9** opened_texture) {
+ TRACE_EVENT0("gpu", "OpenSharedTexture");
HANDLE handle = reinterpret_cast<HANDLE>(surface_handle);
HRESULT hr = device->CreateTexture(size.width(),
size.height(),
@@ -83,37 +85,49 @@ bool OpenSharedTexture(IDirect3DDevice9* device,
return SUCCEEDED(hr);
}
-bool CreateTemporaryLockableSurface(IDirect3DDevice9* device,
- const gfx::Size& size,
- IDirect3DSurface9** surface) {
- HRESULT hr = device->CreateRenderTarget(
- size.width(),
- size.height(),
- D3DFMT_A8R8G8B8,
- D3DMULTISAMPLE_NONE,
- 0,
- TRUE,
- surface,
- NULL);
- return SUCCEEDED(hr);
+bool CreateOrReuseLockableSurface(
+ IDirect3DDevice9* device,
+ const gfx::Size& size,
+ base::win::ScopedComPtr<IDirect3DSurface9>* surface) {
+ if (!*surface || GetSize(*surface) != size) {
+ TRACE_EVENT0("gpu", "CreateRenderTarget");
+ surface->Release();
+ HRESULT hr = device->CreateRenderTarget(
+ size.width(),
+ size.height(),
+ D3DFMT_A8R8G8B8,
+ D3DMULTISAMPLE_NONE,
+ 0,
+ TRUE,
+ surface->Receive(),
+ NULL);
+ if (FAILED(hr))
+ return false;
+ }
+ return true;
}
-bool CreateTemporaryRenderTargetTexture(IDirect3DDevice9* device,
- const gfx::Size& size,
- IDirect3DTexture9** texture,
- IDirect3DSurface9** render_target) {
- HRESULT hr = device->CreateTexture(
- size.width(),
- size.height(),
- 1, // Levels
- D3DUSAGE_RENDERTARGET,
- D3DFMT_A8R8G8B8,
- D3DPOOL_DEFAULT,
- texture,
- NULL);
- if (!SUCCEEDED(hr))
- return false;
- hr = (*texture)->GetSurfaceLevel(0, render_target);
+bool CreateOrReuseRenderTargetTexture(
+ IDirect3DDevice9* device,
+ const gfx::Size& size,
+ base::win::ScopedComPtr<IDirect3DTexture9>* texture,
+ IDirect3DSurface9** render_target) {
+ if (!*texture || GetSize(*texture) != size) {
+ TRACE_EVENT0("gpu", "CreateTexture");
+ texture->Release();
+ HRESULT hr = device->CreateTexture(
+ size.width(),
+ size.height(),
+ 1, // Levels
+ D3DUSAGE_RENDERTARGET,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_DEFAULT,
+ texture->Receive(),
+ NULL);
+ if (!SUCCEEDED(hr))
+ return false;
+ }
+ HRESULT hr = (*texture)->GetSurfaceLevel(0, render_target);
return SUCCEEDED(hr);
}
diff --git a/ui/surface/d3d9_utils_win.h b/ui/surface/d3d9_utils_win.h
index 4f11a3a..58d1918 100644
--- a/ui/surface/d3d9_utils_win.h
+++ b/ui/surface/d3d9_utils_win.h
@@ -11,6 +11,7 @@
#include <d3d9.h>
#include "base/basictypes.h"
+#include "base/win/scoped_comptr.h"
#include "ui/surface/surface_export.h"
namespace base {
@@ -35,10 +36,11 @@ bool CreateDevice(const base::ScopedNativeLibrary& d3d_module,
uint32 presentation_interval,
IDirect3DDevice9Ex** device);
-// Calls the Vista+ (WDDM1.0) variant of CreateTexture that semantically
-// opens a texture allocated (possibly in another process) as shared. The
-// shared texture is identified by its surface handle. The resulting texture
-// is written into |opened_texture|.
+// Calls the Vista+ (WDDM1.0) variant of CreateTexture that semantically opens a
+// texture allocated as shared. In this way textures allocated by another
+// process can be used by a D3D context in this process. The shared texture is
+// identified by its surface handle. The resulting texture is written into
+// |opened_texture|.
//
// Returns true on success.
SURFACE_EXPORT
@@ -47,24 +49,31 @@ bool OpenSharedTexture(IDirect3DDevice9* device,
const gfx::Size& size,
IDirect3DTexture9** opened_texture);
-// Create a one-off lockable surface of a specified size.
+// Ensures that |surface| is a lockable surface of a specified |size|. If
+// |*surface| is non-null and has dimensions that match |size|, it is reused.
+// Otherwise, a new resource is created and the old one (if any) is freed.
//
// Returns true on success.
SURFACE_EXPORT
-bool CreateTemporaryLockableSurface(IDirect3DDevice9* device,
- const gfx::Size& size,
- IDirect3DSurface9** surface);
-
-// Create a one-off renderable texture of a specified size. The texture object
-// as well as the surface object for the texture's level 0 is returned (callers
-// almost always need to use both).
+bool CreateOrReuseLockableSurface(
+ IDirect3DDevice9* device,
+ const gfx::Size& size,
+ base::win::ScopedComPtr<IDirect3DSurface9>* surface);
+
+// Ensures that |texture| is a render target texture of a specified |size|. If
+// |*texture| is non-null and has dimensions that match |size|, it is reused.
+// Otherwise, a new resource is created and the old one (if any) is freed.
+//
+// A reference to level 0 of the resulting texture is placed into
+// |render_target|.
//
// Returns true on success.
SURFACE_EXPORT
-bool CreateTemporaryRenderTargetTexture(IDirect3DDevice9* device,
- const gfx::Size& size,
- IDirect3DTexture9** texture,
- IDirect3DSurface9** render_target);
+bool CreateOrReuseRenderTargetTexture(
+ IDirect3DDevice9* device,
+ const gfx::Size& size,
+ base::win::ScopedComPtr<IDirect3DTexture9>* texture,
+ IDirect3DSurface9** render_target);
SURFACE_EXPORT
gfx::Size GetSize(IDirect3DTexture9* texture);
@@ -74,4 +83,4 @@ gfx::Size GetSize(IDirect3DSurface9* surface);
} // namespace ui_surface_d3d9_utils
-#endif // UI_SURFACE_D3D9_UTILS_WIN_H_ \ No newline at end of file
+#endif // UI_SURFACE_D3D9_UTILS_WIN_H_