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