• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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