summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/windows/d3d11_texture_wrapper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/gpu/windows/d3d11_texture_wrapper.cc')
-rw-r--r--chromium/media/gpu/windows/d3d11_texture_wrapper.cc170
1 files changed, 170 insertions, 0 deletions
diff --git a/chromium/media/gpu/windows/d3d11_texture_wrapper.cc b/chromium/media/gpu/windows/d3d11_texture_wrapper.cc
new file mode 100644
index 00000000000..66b9e73ad58
--- /dev/null
+++ b/chromium/media/gpu/windows/d3d11_texture_wrapper.cc
@@ -0,0 +1,170 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/windows/d3d11_texture_wrapper.h"
+
+#include <memory>
+
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "media/gpu/windows/return_on_failure.h"
+
+namespace media {
+
+Texture2DWrapper::Texture2DWrapper(ComD3D11Texture2D texture)
+ : texture_(texture) {}
+
+Texture2DWrapper::~Texture2DWrapper() {}
+
+const ComD3D11Texture2D Texture2DWrapper::Texture() const {
+ return texture_;
+}
+
+DefaultTexture2DWrapper::DefaultTexture2DWrapper(ComD3D11Texture2D texture)
+ : Texture2DWrapper(texture) {}
+DefaultTexture2DWrapper::~DefaultTexture2DWrapper() {}
+
+const MailboxHolderArray& DefaultTexture2DWrapper::ProcessTexture(
+ const D3D11PictureBuffer* owner_pb) {
+ return mailbox_holders_;
+}
+
+bool DefaultTexture2DWrapper::Init(GetCommandBufferHelperCB get_helper_cb,
+ size_t array_slice,
+ GLenum target,
+ gfx::Size size,
+ int textures_per_picture) {
+ gpu_resources_ = std::make_unique<GpuResources>();
+ if (!gpu_resources_)
+ return false;
+
+ // Generate mailboxes and holders.
+ std::vector<gpu::Mailbox> mailboxes;
+ for (int texture_idx = 0; texture_idx < textures_per_picture; texture_idx++) {
+ mailboxes.push_back(gpu::Mailbox::Generate());
+ mailbox_holders_[texture_idx] = gpu::MailboxHolder(
+ mailboxes[texture_idx], gpu::SyncToken(), GL_TEXTURE_EXTERNAL_OES);
+ }
+
+ // Start construction of the GpuResources.
+ // We send the texture itself, since we assume that we're using the angle
+ // device for decoding. Sharing seems not to work very well. Otherwise, we
+ // would create the texture with KEYED_MUTEX and NTHANDLE, then send along
+ // a handle that we get from |texture| as an IDXGIResource1.
+ // TODO(liberato): this should happen on the gpu thread.
+ return gpu_resources_->Init(std::move(get_helper_cb), array_slice,
+ std::move(mailboxes), target, size, Texture(),
+ textures_per_picture);
+
+ return true;
+}
+
+DefaultTexture2DWrapper::GpuResources::GpuResources() {}
+
+DefaultTexture2DWrapper::GpuResources::~GpuResources() {
+ if (helper_ && helper_->MakeContextCurrent()) {
+ for (uint32_t service_id : service_ids_)
+ helper_->DestroyTexture(service_id);
+ }
+}
+
+bool DefaultTexture2DWrapper::GpuResources::Init(
+ GetCommandBufferHelperCB get_helper_cb,
+ int array_slice,
+ const std::vector<gpu::Mailbox> mailboxes,
+ GLenum target,
+ gfx::Size size,
+ ComD3D11Texture2D angle_texture,
+ int textures_per_picture) {
+ helper_ = get_helper_cb.Run();
+
+ if (!helper_ || !helper_->MakeContextCurrent())
+ return false;
+
+ // Create the textures and attach them to the mailboxes.
+ for (int texture_idx = 0; texture_idx < textures_per_picture; texture_idx++) {
+ uint32_t service_id =
+ helper_->CreateTexture(target, GL_RGBA, size.width(), size.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE);
+ service_ids_.push_back(service_id);
+ helper_->ProduceTexture(mailboxes[texture_idx], service_id);
+ }
+
+ // Create the stream for zero-copy use by gl.
+ EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
+ const EGLint stream_attributes[] = {
+ EGL_CONSUMER_LATENCY_USEC_KHR,
+ 0,
+ EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR,
+ 0,
+ EGL_NONE,
+ };
+ EGLStreamKHR stream = eglCreateStreamKHR(egl_display, stream_attributes);
+ RETURN_ON_FAILURE(!!stream, "Could not create stream", false);
+
+ // |stream| will be destroyed when the GLImage is.
+ // TODO(liberato): for tests, it will be destroyed pretty much at the end of
+ // this function unless |helper_| retains it. Also, this won't work if we
+ // have a FakeCommandBufferHelper since the service IDs aren't meaningful.
+ scoped_refptr<gl::GLImage> gl_image =
+ base::MakeRefCounted<gl::GLImageDXGI>(size, stream);
+ gl::ScopedActiveTexture texture0(GL_TEXTURE0);
+ gl::ScopedTextureBinder texture0_binder(GL_TEXTURE_EXTERNAL_OES,
+ service_ids_[0]);
+ gl::ScopedActiveTexture texture1(GL_TEXTURE1);
+ gl::ScopedTextureBinder texture1_binder(GL_TEXTURE_EXTERNAL_OES,
+ service_ids_[1]);
+
+ EGLAttrib consumer_attributes[] = {
+ EGL_COLOR_BUFFER_TYPE,
+ EGL_YUV_BUFFER_EXT,
+ EGL_YUV_NUMBER_OF_PLANES_EXT,
+ 2,
+ EGL_YUV_PLANE0_TEXTURE_UNIT_NV,
+ 0,
+ EGL_YUV_PLANE1_TEXTURE_UNIT_NV,
+ 1,
+ EGL_NONE,
+ };
+ EGLBoolean result = eglStreamConsumerGLTextureExternalAttribsNV(
+ egl_display, stream, consumer_attributes);
+ RETURN_ON_FAILURE(result, "Could not set stream consumer", false);
+
+ EGLAttrib producer_attributes[] = {
+ EGL_NONE,
+ };
+
+ result = eglCreateStreamProducerD3DTextureANGLE(egl_display, stream,
+ producer_attributes);
+ RETURN_ON_FAILURE(result, "Could not create stream", false);
+
+ EGLAttrib frame_attributes[] = {
+ EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
+ array_slice,
+ EGL_NONE,
+ };
+
+ result = eglStreamPostD3DTextureANGLE(egl_display, stream,
+ static_cast<void*>(angle_texture.Get()),
+ frame_attributes);
+ RETURN_ON_FAILURE(result, "Could not post texture", false);
+
+ result = eglStreamConsumerAcquireKHR(egl_display, stream);
+
+ RETURN_ON_FAILURE(result, "Could not post acquire stream", false);
+ gl::GLImageDXGI* gl_image_dxgi =
+ static_cast<gl::GLImageDXGI*>(gl_image.get());
+
+ gl_image_dxgi->SetTexture(angle_texture, array_slice);
+
+ // Bind the image to each texture.
+ for (size_t texture_idx = 0; texture_idx < service_ids_.size();
+ texture_idx++) {
+ helper_->BindImage(service_ids_[texture_idx], gl_image.get(),
+ false /* client_managed */);
+ }
+
+ return true;
+}
+
+} // namespace media