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