blob: f1190e3834f474119608d361175a6db50b19ff19 [file] [log] [blame]
// Copyright 2018 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
//
// Portions Copyright (c) 2018 Daktronics with the following MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_
#pragma once
#include <d3d11_1.h>
#include <memory>
#include <string>
#include <vector>
#include "include/base/cef_macros.h"
namespace client {
namespace d3d11 {
class Composition;
class Context;
class Effect;
class Geometry;
class SwapChain;
class Texture2D;
// Basic rect for floats.
struct Rect {
float x;
float y;
float width;
float height;
};
template <class T>
class ScopedBinder {
public:
ScopedBinder(const std::shared_ptr<Context>& ctx,
const std::shared_ptr<T>& target)
: target_(target) {
if (target_) {
target_->bind(ctx);
}
}
~ScopedBinder() {
if (target_) {
target_->unbind();
}
}
private:
const std::shared_ptr<T> target_;
DISALLOW_COPY_AND_ASSIGN(ScopedBinder);
};
class Context {
public:
Context(ID3D11DeviceContext*);
void flush();
operator ID3D11DeviceContext*() { return ctx_.get(); }
private:
const std::shared_ptr<ID3D11DeviceContext> ctx_;
};
// Encapsulate a D3D11 Device object.
class Device {
public:
Device(ID3D11Device*, ID3D11DeviceContext*);
static std::shared_ptr<Device> create();
std::string adapter_name() const;
operator ID3D11Device*() { return device_.get(); }
std::shared_ptr<Context> immedidate_context();
std::shared_ptr<SwapChain> create_swapchain(HWND,
int width = 0,
int height = 0);
std::shared_ptr<Geometry> create_quad(float x,
float y,
float width,
float height,
bool flip = false);
std::shared_ptr<Texture2D> create_texture(int width,
int height,
DXGI_FORMAT format,
const void* data,
size_t row_stride);
std::shared_ptr<Texture2D> open_shared_texture(void*);
// Create some basic shaders so we can draw a textured-quad.
std::shared_ptr<Effect> create_default_effect();
std::shared_ptr<Effect> create_effect(const std::string& vertex_code,
const std::string& vertex_entry,
const std::string& vertex_model,
const std::string& pixel_code,
const std::string& pixel_entry,
const std::string& pixel_model);
private:
std::shared_ptr<ID3DBlob> compile_shader(const std::string& source_code,
const std::string& entry_point,
const std::string& model);
HMODULE lib_compiler_;
const std::shared_ptr<ID3D11Device> device_;
const std::shared_ptr<Context> ctx_;
DISALLOW_COPY_AND_ASSIGN(Device);
};
// Encapsulate a DXGI swapchain for a window.
class SwapChain {
public:
SwapChain(IDXGISwapChain*,
ID3D11RenderTargetView*,
ID3D11SamplerState*,
ID3D11BlendState*);
void bind(const std::shared_ptr<Context>& ctx);
void unbind();
void clear(float red, float green, float blue, float alpha);
void present(int sync_interval);
void resize(int width, int height);
int width() const { return width_; }
int height() const { return height_; }
private:
const std::shared_ptr<ID3D11SamplerState> sampler_;
const std::shared_ptr<ID3D11BlendState> blender_;
const std::shared_ptr<IDXGISwapChain> swapchain_;
std::shared_ptr<ID3D11RenderTargetView> rtv_;
std::shared_ptr<Context> ctx_;
int width_;
int height_;
DISALLOW_COPY_AND_ASSIGN(SwapChain);
};
class Texture2D {
public:
Texture2D(ID3D11Texture2D* tex, ID3D11ShaderResourceView* srv);
void bind(std::shared_ptr<Context> const& ctx);
void unbind();
uint32_t width() const;
uint32_t height() const;
DXGI_FORMAT format() const;
bool has_mutex() const;
bool lock_key(uint64_t key, uint32_t timeout_ms);
void unlock_key(uint64_t key);
void* share_handle() const;
void copy_from(const std::shared_ptr<Texture2D>&);
private:
HANDLE share_handle_;
const std::shared_ptr<ID3D11Texture2D> texture_;
const std::shared_ptr<ID3D11ShaderResourceView> srv_;
std::shared_ptr<IDXGIKeyedMutex> keyed_mutex_;
std::shared_ptr<Context> ctx_;
DISALLOW_COPY_AND_ASSIGN(Texture2D);
};
class Effect {
public:
Effect(ID3D11VertexShader* vsh,
ID3D11PixelShader* psh,
ID3D11InputLayout* layout);
void bind(const std::shared_ptr<Context>& ctx);
void unbind();
private:
const std::shared_ptr<ID3D11VertexShader> vsh_;
const std::shared_ptr<ID3D11PixelShader> psh_;
const std::shared_ptr<ID3D11InputLayout> layout_;
std::shared_ptr<Context> ctx_;
DISALLOW_COPY_AND_ASSIGN(Effect);
};
class Geometry {
public:
Geometry(D3D_PRIMITIVE_TOPOLOGY primitive,
uint32_t vertices,
uint32_t stride,
ID3D11Buffer*);
void bind(const std::shared_ptr<Context>& ctx);
void unbind();
void draw();
private:
D3D_PRIMITIVE_TOPOLOGY primitive_;
uint32_t vertices_;
uint32_t stride_;
const std::shared_ptr<ID3D11Buffer> buffer_;
std::shared_ptr<Context> ctx_;
DISALLOW_COPY_AND_ASSIGN(Geometry);
};
// Abstraction for a 2D layer within a composition.
class Layer {
public:
Layer(const std::shared_ptr<Device>& device, bool flip);
virtual ~Layer();
void attach(const std::shared_ptr<Composition>&);
// Uses normalized 0-1.0 coordinates.
virtual void move(float x, float y, float width, float height);
virtual void tick(double t);
virtual void render(const std::shared_ptr<Context>& ctx) = 0;
Rect bounds() const;
std::shared_ptr<Composition> composition() const;
protected:
// Helper method for derived classes to draw a textured-quad.
void render_texture(const std::shared_ptr<Context>& ctx,
const std::shared_ptr<Texture2D>& texture);
const std::shared_ptr<Device> device_;
const bool flip_;
Rect bounds_;
std::shared_ptr<Geometry> geometry_;
std::shared_ptr<Effect> effect_;
private:
std::weak_ptr<Composition> composition_;
DISALLOW_COPY_AND_ASSIGN(Layer);
};
// A collection of layers. Will render 1-N layers to a D3D11 device.
class Composition : public std::enable_shared_from_this<Composition> {
public:
Composition(const std::shared_ptr<Device>& device,
int width = 0,
int height = 0);
int width() const { return width_; }
int height() const { return height_; }
double fps() const;
double time() const;
bool is_vsync() const;
void tick(double);
void render(const std::shared_ptr<Context>&);
void add_layer(const std::shared_ptr<Layer>& layer);
bool remove_layer(const std::shared_ptr<Layer>& layer);
void resize(bool vsync, int width, int height);
private:
int width_;
int height_;
uint32_t frame_;
int64_t fps_start_;
double fps_;
double time_;
bool vsync_;
const std::shared_ptr<Device> device_;
std::vector<std::shared_ptr<Layer>> layers_;
DISALLOW_COPY_AND_ASSIGN(Composition);
};
class FrameBuffer {
public:
explicit FrameBuffer(const std::shared_ptr<Device>& device);
// Called in response to CEF's OnAcceleratedPaint notification.
void on_paint(void* shared_handle);
// Returns what should be considered the front buffer.
std::shared_ptr<Texture2D> texture() const { return shared_buffer_; }
private:
const std::shared_ptr<Device> device_;
std::shared_ptr<Texture2D> shared_buffer_;
DISALLOW_COPY_AND_ASSIGN(FrameBuffer);
};
} // namespace d3d11
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_OSR_D3D11_WIN_H_