1 // Copyright 2018 The Chromium Embedded Framework Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be found 3 // in the LICENSE file. 4 // 5 // Portions Copyright (c) 2018 Daktronics with the following MIT License: 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 17 #ifndef CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_ 18 #define CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_ 19 #pragma once 20 21 #include <d3d11_1.h> 22 23 #include <memory> 24 #include <string> 25 #include <vector> 26 27 #include "include/base/cef_macros.h" 28 29 namespace client { 30 namespace d3d11 { 31 32 class Composition; 33 class Context; 34 class Effect; 35 class Geometry; 36 class SwapChain; 37 class Texture2D; 38 39 // Basic rect for floats. 40 struct Rect { 41 float x; 42 float y; 43 float width; 44 float height; 45 }; 46 47 template <class T> 48 class ScopedBinder { 49 public: ScopedBinder(const std::shared_ptr<Context> & ctx,const std::shared_ptr<T> & target)50 ScopedBinder(const std::shared_ptr<Context>& ctx, 51 const std::shared_ptr<T>& target) 52 : target_(target) { 53 if (target_) { 54 target_->bind(ctx); 55 } 56 } ~ScopedBinder()57 ~ScopedBinder() { 58 if (target_) { 59 target_->unbind(); 60 } 61 } 62 63 private: 64 const std::shared_ptr<T> target_; 65 66 DISALLOW_COPY_AND_ASSIGN(ScopedBinder); 67 }; 68 69 class Context { 70 public: 71 Context(ID3D11DeviceContext*); 72 73 void flush(); 74 75 operator ID3D11DeviceContext*() { return ctx_.get(); } 76 77 private: 78 const std::shared_ptr<ID3D11DeviceContext> ctx_; 79 }; 80 81 // Encapsulate a D3D11 Device object. 82 class Device { 83 public: 84 Device(ID3D11Device*, ID3D11DeviceContext*); 85 86 static std::shared_ptr<Device> create(); 87 88 std::string adapter_name() const; 89 90 operator ID3D11Device*() { return device_.get(); } 91 92 std::shared_ptr<Context> immedidate_context(); 93 94 std::shared_ptr<SwapChain> create_swapchain(HWND, 95 int width = 0, 96 int height = 0); 97 98 std::shared_ptr<Geometry> create_quad(float x, 99 float y, 100 float width, 101 float height, 102 bool flip = false); 103 104 std::shared_ptr<Texture2D> create_texture(int width, 105 int height, 106 DXGI_FORMAT format, 107 const void* data, 108 size_t row_stride); 109 110 std::shared_ptr<Texture2D> open_shared_texture(void*); 111 112 // Create some basic shaders so we can draw a textured-quad. 113 std::shared_ptr<Effect> create_default_effect(); 114 115 std::shared_ptr<Effect> create_effect(const std::string& vertex_code, 116 const std::string& vertex_entry, 117 const std::string& vertex_model, 118 const std::string& pixel_code, 119 const std::string& pixel_entry, 120 const std::string& pixel_model); 121 122 private: 123 std::shared_ptr<ID3DBlob> compile_shader(const std::string& source_code, 124 const std::string& entry_point, 125 const std::string& model); 126 127 HMODULE lib_compiler_; 128 129 const std::shared_ptr<ID3D11Device> device_; 130 const std::shared_ptr<Context> ctx_; 131 132 DISALLOW_COPY_AND_ASSIGN(Device); 133 }; 134 135 // Encapsulate a DXGI swapchain for a window. 136 class SwapChain { 137 public: 138 SwapChain(IDXGISwapChain*, 139 ID3D11RenderTargetView*, 140 ID3D11SamplerState*, 141 ID3D11BlendState*); 142 143 void bind(const std::shared_ptr<Context>& ctx); 144 void unbind(); 145 146 void clear(float red, float green, float blue, float alpha); 147 148 void present(int sync_interval); 149 void resize(int width, int height); 150 width()151 int width() const { return width_; } height()152 int height() const { return height_; } 153 154 private: 155 const std::shared_ptr<ID3D11SamplerState> sampler_; 156 const std::shared_ptr<ID3D11BlendState> blender_; 157 const std::shared_ptr<IDXGISwapChain> swapchain_; 158 std::shared_ptr<ID3D11RenderTargetView> rtv_; 159 std::shared_ptr<Context> ctx_; 160 int width_; 161 int height_; 162 163 DISALLOW_COPY_AND_ASSIGN(SwapChain); 164 }; 165 166 class Texture2D { 167 public: 168 Texture2D(ID3D11Texture2D* tex, ID3D11ShaderResourceView* srv); 169 170 void bind(std::shared_ptr<Context> const& ctx); 171 void unbind(); 172 173 uint32_t width() const; 174 uint32_t height() const; 175 DXGI_FORMAT format() const; 176 177 bool has_mutex() const; 178 179 bool lock_key(uint64_t key, uint32_t timeout_ms); 180 void unlock_key(uint64_t key); 181 182 void* share_handle() const; 183 184 void copy_from(const std::shared_ptr<Texture2D>&); 185 186 private: 187 HANDLE share_handle_; 188 189 const std::shared_ptr<ID3D11Texture2D> texture_; 190 const std::shared_ptr<ID3D11ShaderResourceView> srv_; 191 std::shared_ptr<IDXGIKeyedMutex> keyed_mutex_; 192 std::shared_ptr<Context> ctx_; 193 194 DISALLOW_COPY_AND_ASSIGN(Texture2D); 195 }; 196 197 class Effect { 198 public: 199 Effect(ID3D11VertexShader* vsh, 200 ID3D11PixelShader* psh, 201 ID3D11InputLayout* layout); 202 203 void bind(const std::shared_ptr<Context>& ctx); 204 void unbind(); 205 206 private: 207 const std::shared_ptr<ID3D11VertexShader> vsh_; 208 const std::shared_ptr<ID3D11PixelShader> psh_; 209 const std::shared_ptr<ID3D11InputLayout> layout_; 210 std::shared_ptr<Context> ctx_; 211 212 DISALLOW_COPY_AND_ASSIGN(Effect); 213 }; 214 215 class Geometry { 216 public: 217 Geometry(D3D_PRIMITIVE_TOPOLOGY primitive, 218 uint32_t vertices, 219 uint32_t stride, 220 ID3D11Buffer*); 221 222 void bind(const std::shared_ptr<Context>& ctx); 223 void unbind(); 224 225 void draw(); 226 227 private: 228 D3D_PRIMITIVE_TOPOLOGY primitive_; 229 uint32_t vertices_; 230 uint32_t stride_; 231 const std::shared_ptr<ID3D11Buffer> buffer_; 232 std::shared_ptr<Context> ctx_; 233 234 DISALLOW_COPY_AND_ASSIGN(Geometry); 235 }; 236 237 // Abstraction for a 2D layer within a composition. 238 class Layer { 239 public: 240 Layer(const std::shared_ptr<Device>& device, bool flip); 241 virtual ~Layer(); 242 243 void attach(const std::shared_ptr<Composition>&); 244 245 // Uses normalized 0-1.0 coordinates. 246 virtual void move(float x, float y, float width, float height); 247 248 virtual void tick(double t); 249 virtual void render(const std::shared_ptr<Context>& ctx) = 0; 250 251 Rect bounds() const; 252 253 std::shared_ptr<Composition> composition() const; 254 255 protected: 256 // Helper method for derived classes to draw a textured-quad. 257 void render_texture(const std::shared_ptr<Context>& ctx, 258 const std::shared_ptr<Texture2D>& texture); 259 260 const std::shared_ptr<Device> device_; 261 const bool flip_; 262 263 Rect bounds_; 264 std::shared_ptr<Geometry> geometry_; 265 std::shared_ptr<Effect> effect_; 266 267 private: 268 std::weak_ptr<Composition> composition_; 269 270 DISALLOW_COPY_AND_ASSIGN(Layer); 271 }; 272 273 // A collection of layers. Will render 1-N layers to a D3D11 device. 274 class Composition : public std::enable_shared_from_this<Composition> { 275 public: 276 Composition(const std::shared_ptr<Device>& device, 277 int width = 0, 278 int height = 0); 279 width()280 int width() const { return width_; } height()281 int height() const { return height_; } 282 283 double fps() const; 284 double time() const; 285 286 bool is_vsync() const; 287 288 void tick(double); 289 void render(const std::shared_ptr<Context>&); 290 291 void add_layer(const std::shared_ptr<Layer>& layer); 292 bool remove_layer(const std::shared_ptr<Layer>& layer); 293 void resize(bool vsync, int width, int height); 294 295 private: 296 int width_; 297 int height_; 298 uint32_t frame_; 299 int64_t fps_start_; 300 double fps_; 301 double time_; 302 bool vsync_; 303 304 const std::shared_ptr<Device> device_; 305 std::vector<std::shared_ptr<Layer>> layers_; 306 307 DISALLOW_COPY_AND_ASSIGN(Composition); 308 }; 309 310 class FrameBuffer { 311 public: 312 explicit FrameBuffer(const std::shared_ptr<Device>& device); 313 314 // Called in response to CEF's OnAcceleratedPaint notification. 315 void on_paint(void* shared_handle); 316 317 // Returns what should be considered the front buffer. texture()318 std::shared_ptr<Texture2D> texture() const { return shared_buffer_; } 319 320 private: 321 const std::shared_ptr<Device> device_; 322 std::shared_ptr<Texture2D> shared_buffer_; 323 324 DISALLOW_COPY_AND_ASSIGN(FrameBuffer); 325 }; 326 327 } // namespace d3d11 328 } // namespace client 329 330 #endif // CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_ 331