| Index: content/common/gpu/media/dxva_video_decode_accelerator.cc
|
| ===================================================================
|
| --- content/common/gpu/media/dxva_video_decode_accelerator.cc (revision 166997)
|
| +++ content/common/gpu/media/dxva_video_decode_accelerator.cc (working copy)
|
| @@ -10,7 +10,6 @@
|
|
|
| #include <ks.h>
|
| #include <codecapi.h>
|
| -#include <d3dx9tex.h>
|
| #include <mfapi.h>
|
| #include <mferror.h>
|
| #include <wmcodecdsp.h>
|
| @@ -158,81 +157,6 @@
|
| alignment);
|
| }
|
|
|
| -// Helper function to read the bitmap from the D3D surface passed in.
|
| -static bool GetBitmapFromSurface(IDirect3DDevice9Ex* device,
|
| - IDirect3DSurface9* surface,
|
| - scoped_array<char>* bits) {
|
| - // TODO(ananta)
|
| - // The code below may not be necessary once we have an ANGLE extension which
|
| - // allows us to pass the Direct 3D surface directly for rendering.
|
| -
|
| - // The decoded bits in the source direct 3d surface are in the YUV
|
| - // format. Angle does not support that. As a workaround we create an
|
| - // offscreen surface in the RGB format and copy the source surface
|
| - // to this surface.
|
| - D3DSURFACE_DESC surface_desc;
|
| - HRESULT hr = surface->GetDesc(&surface_desc);
|
| - RETURN_ON_HR_FAILURE(hr, "Failed to get surface description", false);
|
| -
|
| - base::win::ScopedComPtr<IDirect3DSurface9> dest_surface;
|
| - hr = device->CreateOffscreenPlainSurface(surface_desc.Width,
|
| - surface_desc.Height,
|
| - D3DFMT_A8R8G8B8,
|
| - D3DPOOL_DEFAULT,
|
| - dest_surface.Receive(),
|
| - NULL);
|
| - RETURN_ON_HR_FAILURE(hr, "Failed to create offscreen surface", false);
|
| -
|
| - hr = D3DXLoadSurfaceFromSurface(dest_surface, NULL, NULL, surface, NULL,
|
| - NULL, D3DX_DEFAULT, 0);
|
| - RETURN_ON_HR_FAILURE(hr, "D3DXLoadSurfaceFromSurface failed", false);
|
| -
|
| - // Get the currently loaded bitmap from the DC.
|
| - HDC hdc = NULL;
|
| - hr = dest_surface->GetDC(&hdc);
|
| - RETURN_ON_HR_FAILURE(hr, "Failed to get HDC from surface", false);
|
| -
|
| - HBITMAP bitmap =
|
| - reinterpret_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
|
| - if (!bitmap) {
|
| - NOTREACHED() << "Failed to get bitmap from DC";
|
| - dest_surface->ReleaseDC(hdc);
|
| - return false;
|
| - }
|
| -
|
| - BITMAP bitmap_basic_info = {0};
|
| - if (!GetObject(bitmap, sizeof(BITMAP), &bitmap_basic_info)) {
|
| - NOTREACHED() << "Failed to read bitmap info";
|
| - dest_surface->ReleaseDC(hdc);
|
| - return false;
|
| - }
|
| - BITMAPINFO bitmap_info = {0};
|
| - bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
| - bitmap_info.bmiHeader.biWidth = bitmap_basic_info.bmWidth;
|
| - bitmap_info.bmiHeader.biHeight = bitmap_basic_info.bmHeight;
|
| - bitmap_info.bmiHeader.biPlanes = 1;
|
| - bitmap_info.bmiHeader.biBitCount = bitmap_basic_info.bmBitsPixel;
|
| - bitmap_info.bmiHeader.biCompression = BI_RGB;
|
| - bitmap_info.bmiHeader.biSizeImage = 0;
|
| - bitmap_info.bmiHeader.biClrUsed = 0;
|
| -
|
| - int ret = GetDIBits(hdc, bitmap, 0, 0, NULL, &bitmap_info, DIB_RGB_COLORS);
|
| - if (!ret || bitmap_info.bmiHeader.biSizeImage <= 0) {
|
| - NOTREACHED() << "Failed to read bitmap size";
|
| - dest_surface->ReleaseDC(hdc);
|
| - return false;
|
| - }
|
| -
|
| - bits->reset(new char[bitmap_info.bmiHeader.biSizeImage]);
|
| - ret = GetDIBits(hdc, bitmap, 0, bitmap_basic_info.bmHeight, bits->get(),
|
| - &bitmap_info, DIB_RGB_COLORS);
|
| - if (!ret) {
|
| - NOTREACHED() << "Failed to retrieve bitmap bits.";
|
| - }
|
| - dest_surface->ReleaseDC(hdc);
|
| - return !!ret;
|
| -}
|
| -
|
| // Maintains information about a DXVA picture buffer, i.e. whether it is
|
| // available for rendering, the texture information, etc.
|
| struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
|
| @@ -371,6 +295,10 @@
|
| D3DFMT_X8R8G8B8);
|
| bool device_supports_format_conversion = (hr == S_OK);
|
|
|
| + RETURN_ON_FAILURE(device_supports_format_conversion,
|
| + "Device does not support format converision",
|
| + false);
|
| +
|
| // This function currently executes in the context of IPC handlers in the
|
| // GPU process which ensures that there is always an OpenGL context.
|
| GLint current_texture = 0;
|
| @@ -380,41 +308,32 @@
|
|
|
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
| - if (device_supports_format_conversion) {
|
| - base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface;
|
| - HRESULT hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive());
|
| - RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
|
| + base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface;
|
| + hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive());
|
| + RETURN_ON_HR_FAILURE(hr, "Failed to get surface from texture", false);
|
|
|
| - hr = device_->StretchRect(dest_surface,
|
| - NULL,
|
| - d3d_surface,
|
| - NULL,
|
| - D3DTEXF_NONE);
|
| - RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",
|
| - false);
|
| - // Ideally, this should be done immediately before the draw call that uses
|
| - // the texture. Flush it once here though.
|
| - hr = query_->Issue(D3DISSUE_END);
|
| - RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false);
|
| - do {
|
| - hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
| - if (hr == S_FALSE)
|
| - Sleep(1); // Poor-man's Yield().
|
| - } while (hr == S_FALSE);
|
| - eglBindTexImage(
|
| - static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)),
|
| - decoding_surface_,
|
| - EGL_BACK_BUFFER);
|
| - } else {
|
| - scoped_array<char> bits;
|
| - RETURN_ON_FAILURE(GetBitmapFromSurface(DXVAVideoDecodeAccelerator::device_,
|
| - dest_surface, &bits),
|
| - "Failed to get bitmap from surface for rendering",
|
| - false);
|
| - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, surface_desc.Width,
|
| - surface_desc.Height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
|
| - reinterpret_cast<GLvoid*>(bits.get()));
|
| - }
|
| + hr = device_->StretchRect(dest_surface,
|
| + NULL,
|
| + d3d_surface,
|
| + NULL,
|
| + D3DTEXF_NONE);
|
| + RETURN_ON_HR_FAILURE(hr, "Colorspace conversion via StretchRect failed",
|
| + false);
|
| +
|
| + // Ideally, this should be done immediately before the draw call that uses
|
| + // the texture. Flush it once here though.
|
| + hr = query_->Issue(D3DISSUE_END);
|
| + RETURN_ON_HR_FAILURE(hr, "Failed to issue END", false);
|
| + do {
|
| + hr = query_->GetData(NULL, 0, D3DGETDATA_FLUSH);
|
| + if (hr == S_FALSE)
|
| + Sleep(1); // Poor-man's Yield().
|
| + } while (hr == S_FALSE);
|
| + eglBindTexImage(
|
| + static_cast<EGLDisplay*>(eglGetDisplay(EGL_DEFAULT_DISPLAY)),
|
| + decoding_surface_,
|
| + EGL_BACK_BUFFER);
|
| +
|
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
| glBindTexture(GL_TEXTURE_2D, current_texture);
|
| return true;
|
| @@ -435,7 +354,6 @@
|
|
|
| static wchar_t* decoding_dlls[] = {
|
| L"d3d9.dll",
|
| - L"d3dx9_43.dll",
|
| L"dxva2.dll",
|
| L"mf.dll",
|
| L"mfplat.dll",
|
|
|