xref: /aosp_15_r20/external/webrtc/test/win/d3d_renderer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #include "test/win/d3d_renderer.h"
11*d9f75844SAndroid Build Coastguard Worker 
12*d9f75844SAndroid Build Coastguard Worker #include "common_video/libyuv/include/webrtc_libyuv.h"
13*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
16*d9f75844SAndroid Build Coastguard Worker namespace test {
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker struct D3dCustomVertex {
21*d9f75844SAndroid Build Coastguard Worker   float x, y, z;
22*d9f75844SAndroid Build Coastguard Worker   float u, v;
23*d9f75844SAndroid Build Coastguard Worker };
24*d9f75844SAndroid Build Coastguard Worker 
25*d9f75844SAndroid Build Coastguard Worker const char kD3DClassName[] = "d3d_renderer";
26*d9f75844SAndroid Build Coastguard Worker 
CreatePlatformRenderer(const char * window_title,size_t width,size_t height)27*d9f75844SAndroid Build Coastguard Worker VideoRenderer* VideoRenderer::CreatePlatformRenderer(const char* window_title,
28*d9f75844SAndroid Build Coastguard Worker                                                      size_t width,
29*d9f75844SAndroid Build Coastguard Worker                                                      size_t height) {
30*d9f75844SAndroid Build Coastguard Worker   return D3dRenderer::Create(window_title, width, height);
31*d9f75844SAndroid Build Coastguard Worker }
32*d9f75844SAndroid Build Coastguard Worker 
D3dRenderer(size_t width,size_t height)33*d9f75844SAndroid Build Coastguard Worker D3dRenderer::D3dRenderer(size_t width, size_t height)
34*d9f75844SAndroid Build Coastguard Worker     : width_(width),
35*d9f75844SAndroid Build Coastguard Worker       height_(height),
36*d9f75844SAndroid Build Coastguard Worker       hwnd_(NULL),
37*d9f75844SAndroid Build Coastguard Worker       d3d_(nullptr),
38*d9f75844SAndroid Build Coastguard Worker       d3d_device_(nullptr),
39*d9f75844SAndroid Build Coastguard Worker       texture_(nullptr),
40*d9f75844SAndroid Build Coastguard Worker       vertex_buffer_(nullptr) {
41*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(width, 0);
42*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GT(height, 0);
43*d9f75844SAndroid Build Coastguard Worker }
44*d9f75844SAndroid Build Coastguard Worker 
~D3dRenderer()45*d9f75844SAndroid Build Coastguard Worker D3dRenderer::~D3dRenderer() {
46*d9f75844SAndroid Build Coastguard Worker   Destroy();
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker 
WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)49*d9f75844SAndroid Build Coastguard Worker LRESULT WINAPI D3dRenderer::WindowProc(HWND hwnd,
50*d9f75844SAndroid Build Coastguard Worker                                        UINT msg,
51*d9f75844SAndroid Build Coastguard Worker                                        WPARAM wparam,
52*d9f75844SAndroid Build Coastguard Worker                                        LPARAM lparam) {
53*d9f75844SAndroid Build Coastguard Worker   if (msg == WM_DESTROY || (msg == WM_CHAR && wparam == VK_RETURN)) {
54*d9f75844SAndroid Build Coastguard Worker     PostQuitMessage(0);
55*d9f75844SAndroid Build Coastguard Worker     return 0;
56*d9f75844SAndroid Build Coastguard Worker   }
57*d9f75844SAndroid Build Coastguard Worker 
58*d9f75844SAndroid Build Coastguard Worker   return DefWindowProcA(hwnd, msg, wparam, lparam);
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker 
Destroy()61*d9f75844SAndroid Build Coastguard Worker void D3dRenderer::Destroy() {
62*d9f75844SAndroid Build Coastguard Worker   texture_ = nullptr;
63*d9f75844SAndroid Build Coastguard Worker   vertex_buffer_ = nullptr;
64*d9f75844SAndroid Build Coastguard Worker   d3d_device_ = nullptr;
65*d9f75844SAndroid Build Coastguard Worker   d3d_ = nullptr;
66*d9f75844SAndroid Build Coastguard Worker 
67*d9f75844SAndroid Build Coastguard Worker   if (hwnd_ != NULL) {
68*d9f75844SAndroid Build Coastguard Worker     DestroyWindow(hwnd_);
69*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!IsWindow(hwnd_));
70*d9f75844SAndroid Build Coastguard Worker     hwnd_ = NULL;
71*d9f75844SAndroid Build Coastguard Worker   }
72*d9f75844SAndroid Build Coastguard Worker }
73*d9f75844SAndroid Build Coastguard Worker 
Init(const char * window_title)74*d9f75844SAndroid Build Coastguard Worker bool D3dRenderer::Init(const char* window_title) {
75*d9f75844SAndroid Build Coastguard Worker   hwnd_ = CreateWindowA(kD3DClassName, window_title, WS_OVERLAPPEDWINDOW, 0, 0,
76*d9f75844SAndroid Build Coastguard Worker                         static_cast<int>(width_), static_cast<int>(height_),
77*d9f75844SAndroid Build Coastguard Worker                         NULL, NULL, NULL, NULL);
78*d9f75844SAndroid Build Coastguard Worker 
79*d9f75844SAndroid Build Coastguard Worker   if (hwnd_ == NULL) {
80*d9f75844SAndroid Build Coastguard Worker     Destroy();
81*d9f75844SAndroid Build Coastguard Worker     return false;
82*d9f75844SAndroid Build Coastguard Worker   }
83*d9f75844SAndroid Build Coastguard Worker 
84*d9f75844SAndroid Build Coastguard Worker   d3d_ = Direct3DCreate9(D3D_SDK_VERSION);
85*d9f75844SAndroid Build Coastguard Worker   if (d3d_ == nullptr) {
86*d9f75844SAndroid Build Coastguard Worker     Destroy();
87*d9f75844SAndroid Build Coastguard Worker     return false;
88*d9f75844SAndroid Build Coastguard Worker   }
89*d9f75844SAndroid Build Coastguard Worker 
90*d9f75844SAndroid Build Coastguard Worker   D3DPRESENT_PARAMETERS d3d_params = {};
91*d9f75844SAndroid Build Coastguard Worker 
92*d9f75844SAndroid Build Coastguard Worker   d3d_params.Windowed = TRUE;
93*d9f75844SAndroid Build Coastguard Worker   d3d_params.SwapEffect = D3DSWAPEFFECT_COPY;
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker   IDirect3DDevice9* d3d_device;
96*d9f75844SAndroid Build Coastguard Worker   if (d3d_->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd_,
97*d9f75844SAndroid Build Coastguard Worker                          D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3d_params,
98*d9f75844SAndroid Build Coastguard Worker                          &d3d_device) != D3D_OK) {
99*d9f75844SAndroid Build Coastguard Worker     Destroy();
100*d9f75844SAndroid Build Coastguard Worker     return false;
101*d9f75844SAndroid Build Coastguard Worker   }
102*d9f75844SAndroid Build Coastguard Worker   d3d_device_ = d3d_device;
103*d9f75844SAndroid Build Coastguard Worker   d3d_device->Release();
104*d9f75844SAndroid Build Coastguard Worker 
105*d9f75844SAndroid Build Coastguard Worker   IDirect3DVertexBuffer9* vertex_buffer;
106*d9f75844SAndroid Build Coastguard Worker   const int kRectVertices = 4;
107*d9f75844SAndroid Build Coastguard Worker   if (d3d_device_->CreateVertexBuffer(kRectVertices * sizeof(D3dCustomVertex),
108*d9f75844SAndroid Build Coastguard Worker                                       0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED,
109*d9f75844SAndroid Build Coastguard Worker                                       &vertex_buffer, NULL) != D3D_OK) {
110*d9f75844SAndroid Build Coastguard Worker     Destroy();
111*d9f75844SAndroid Build Coastguard Worker     return false;
112*d9f75844SAndroid Build Coastguard Worker   }
113*d9f75844SAndroid Build Coastguard Worker   vertex_buffer_ = vertex_buffer;
114*d9f75844SAndroid Build Coastguard Worker   vertex_buffer->Release();
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker   d3d_device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
117*d9f75844SAndroid Build Coastguard Worker   d3d_device_->SetRenderState(D3DRS_LIGHTING, FALSE);
118*d9f75844SAndroid Build Coastguard Worker   Resize(width_, height_);
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   ShowWindow(hwnd_, SW_SHOWNOACTIVATE);
121*d9f75844SAndroid Build Coastguard Worker   d3d_device_->Present(NULL, NULL, NULL, NULL);
122*d9f75844SAndroid Build Coastguard Worker 
123*d9f75844SAndroid Build Coastguard Worker   return true;
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker 
Create(const char * window_title,size_t width,size_t height)126*d9f75844SAndroid Build Coastguard Worker D3dRenderer* D3dRenderer::Create(const char* window_title,
127*d9f75844SAndroid Build Coastguard Worker                                  size_t width,
128*d9f75844SAndroid Build Coastguard Worker                                  size_t height) {
129*d9f75844SAndroid Build Coastguard Worker   static ATOM wc_atom = 0;
130*d9f75844SAndroid Build Coastguard Worker   if (wc_atom == 0) {
131*d9f75844SAndroid Build Coastguard Worker     WNDCLASSA wc = {};
132*d9f75844SAndroid Build Coastguard Worker 
133*d9f75844SAndroid Build Coastguard Worker     wc.style = CS_HREDRAW | CS_VREDRAW;
134*d9f75844SAndroid Build Coastguard Worker     wc.lpfnWndProc = WindowProc;
135*d9f75844SAndroid Build Coastguard Worker     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
136*d9f75844SAndroid Build Coastguard Worker     wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
137*d9f75844SAndroid Build Coastguard Worker     wc.lpszClassName = kD3DClassName;
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker     wc_atom = RegisterClassA(&wc);
140*d9f75844SAndroid Build Coastguard Worker     if (wc_atom == 0)
141*d9f75844SAndroid Build Coastguard Worker       return nullptr;
142*d9f75844SAndroid Build Coastguard Worker   }
143*d9f75844SAndroid Build Coastguard Worker 
144*d9f75844SAndroid Build Coastguard Worker   D3dRenderer* d3d_renderer = new D3dRenderer(width, height);
145*d9f75844SAndroid Build Coastguard Worker   if (!d3d_renderer->Init(window_title)) {
146*d9f75844SAndroid Build Coastguard Worker     delete d3d_renderer;
147*d9f75844SAndroid Build Coastguard Worker     return nullptr;
148*d9f75844SAndroid Build Coastguard Worker   }
149*d9f75844SAndroid Build Coastguard Worker 
150*d9f75844SAndroid Build Coastguard Worker   return d3d_renderer;
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker 
Resize(size_t width,size_t height)153*d9f75844SAndroid Build Coastguard Worker void D3dRenderer::Resize(size_t width, size_t height) {
154*d9f75844SAndroid Build Coastguard Worker   width_ = width;
155*d9f75844SAndroid Build Coastguard Worker   height_ = height;
156*d9f75844SAndroid Build Coastguard Worker   IDirect3DTexture9* texture;
157*d9f75844SAndroid Build Coastguard Worker 
158*d9f75844SAndroid Build Coastguard Worker   d3d_device_->CreateTexture(static_cast<UINT>(width_),
159*d9f75844SAndroid Build Coastguard Worker                              static_cast<UINT>(height_), 1, 0, D3DFMT_A8R8G8B8,
160*d9f75844SAndroid Build Coastguard Worker                              D3DPOOL_MANAGED, &texture, NULL);
161*d9f75844SAndroid Build Coastguard Worker   texture_ = texture;
162*d9f75844SAndroid Build Coastguard Worker   texture->Release();
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker   // Vertices for the video frame to be rendered to.
165*d9f75844SAndroid Build Coastguard Worker   static const D3dCustomVertex rect[] = {
166*d9f75844SAndroid Build Coastguard Worker       {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f},
167*d9f75844SAndroid Build Coastguard Worker       {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f},
168*d9f75844SAndroid Build Coastguard Worker       {1.0f, -1.0f, 0.0f, 1.0f, 1.0f},
169*d9f75844SAndroid Build Coastguard Worker       {1.0f, 1.0f, 0.0f, 1.0f, 0.0f},
170*d9f75844SAndroid Build Coastguard Worker   };
171*d9f75844SAndroid Build Coastguard Worker 
172*d9f75844SAndroid Build Coastguard Worker   void* buf_data;
173*d9f75844SAndroid Build Coastguard Worker   if (vertex_buffer_->Lock(0, 0, &buf_data, 0) != D3D_OK)
174*d9f75844SAndroid Build Coastguard Worker     return;
175*d9f75844SAndroid Build Coastguard Worker 
176*d9f75844SAndroid Build Coastguard Worker   memcpy(buf_data, &rect, sizeof(rect));
177*d9f75844SAndroid Build Coastguard Worker   vertex_buffer_->Unlock();
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker 
OnFrame(const webrtc::VideoFrame & frame)180*d9f75844SAndroid Build Coastguard Worker void D3dRenderer::OnFrame(const webrtc::VideoFrame& frame) {
181*d9f75844SAndroid Build Coastguard Worker   if (static_cast<size_t>(frame.width()) != width_ ||
182*d9f75844SAndroid Build Coastguard Worker       static_cast<size_t>(frame.height()) != height_) {
183*d9f75844SAndroid Build Coastguard Worker     Resize(static_cast<size_t>(frame.width()),
184*d9f75844SAndroid Build Coastguard Worker            static_cast<size_t>(frame.height()));
185*d9f75844SAndroid Build Coastguard Worker   }
186*d9f75844SAndroid Build Coastguard Worker 
187*d9f75844SAndroid Build Coastguard Worker   D3DLOCKED_RECT lock_rect;
188*d9f75844SAndroid Build Coastguard Worker   if (texture_->LockRect(0, &lock_rect, NULL, 0) != D3D_OK)
189*d9f75844SAndroid Build Coastguard Worker     return;
190*d9f75844SAndroid Build Coastguard Worker 
191*d9f75844SAndroid Build Coastguard Worker   ConvertFromI420(frame, VideoType::kARGB, 0,
192*d9f75844SAndroid Build Coastguard Worker                   static_cast<uint8_t*>(lock_rect.pBits));
193*d9f75844SAndroid Build Coastguard Worker   texture_->UnlockRect(0);
194*d9f75844SAndroid Build Coastguard Worker 
195*d9f75844SAndroid Build Coastguard Worker   d3d_device_->BeginScene();
196*d9f75844SAndroid Build Coastguard Worker   d3d_device_->SetFVF(D3DFVF_CUSTOMVERTEX);
197*d9f75844SAndroid Build Coastguard Worker   d3d_device_->SetStreamSource(0, vertex_buffer_.get(), 0,
198*d9f75844SAndroid Build Coastguard Worker                                sizeof(D3dCustomVertex));
199*d9f75844SAndroid Build Coastguard Worker   d3d_device_->SetTexture(0, texture_.get());
200*d9f75844SAndroid Build Coastguard Worker   d3d_device_->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
201*d9f75844SAndroid Build Coastguard Worker   d3d_device_->EndScene();
202*d9f75844SAndroid Build Coastguard Worker 
203*d9f75844SAndroid Build Coastguard Worker   d3d_device_->Present(NULL, NULL, NULL, NULL);
204*d9f75844SAndroid Build Coastguard Worker }
205*d9f75844SAndroid Build Coastguard Worker }  // namespace test
206*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
207