2018-11-08 21:39:26 +08:00
|
|
|
|
// Copyright (c) 2016-2018 Easy2D - Nomango
|
|
|
|
|
|
//
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
//
|
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
#include "render.h"
|
2018-11-15 17:59:18 +08:00
|
|
|
|
#include "logs.h"
|
2018-11-21 17:18:59 +08:00
|
|
|
|
#include "Factory.h"
|
2018-11-14 01:34:41 +08:00
|
|
|
|
#include "Image.h"
|
2018-11-18 20:26:41 +08:00
|
|
|
|
#include "Transform.hpp"
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
|
|
|
|
|
namespace easy2d
|
|
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
GraphicsDevice::GraphicsDevice()
|
|
|
|
|
|
: fps_text_format_(nullptr)
|
|
|
|
|
|
, fps_text_layout_(nullptr)
|
|
|
|
|
|
, clear_color_(D2D1::ColorF(D2D1::ColorF::Black))
|
|
|
|
|
|
, opacity_(1.f)
|
2018-11-23 14:55:03 +08:00
|
|
|
|
, debug_(false)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
, window_occluded_(false)
|
|
|
|
|
|
, vsync_enabled_(true)
|
|
|
|
|
|
, antialias_(true)
|
|
|
|
|
|
, text_antialias_(TextAntialias::ClearType)
|
2018-11-08 21:39:26 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
GraphicsDevice::~GraphicsDevice()
|
|
|
|
|
|
{
|
|
|
|
|
|
E2D_LOG("Destroying graphics device");
|
2018-11-15 17:59:18 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
ClearImageCache();
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::Init(HWND hwnd, bool vsync, bool debug)
|
|
|
|
|
|
{
|
|
|
|
|
|
E2D_LOG("Initing graphics device");
|
2018-11-15 17:59:18 +08:00
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
vsync_enabled_ = vsync;
|
|
|
|
|
|
debug_ = debug;
|
2018-11-12 22:36:50 +08:00
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
return CreateResources(hwnd);
|
2018-11-22 19:31:44 +08:00
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::BeginDraw(HWND hwnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
HRESULT hr = CreateResources(hwnd);
|
|
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
if (debug_)
|
|
|
|
|
|
{
|
|
|
|
|
|
status_.start = time::Now();
|
|
|
|
|
|
status_.primitives = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
2018-11-12 02:10:35 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
window_occluded_ = !!(render_target_->CheckWindowState() & D2D1_WINDOW_STATE_OCCLUDED);
|
|
|
|
|
|
|
2018-11-21 16:26:52 +08:00
|
|
|
|
if (!window_occluded_)
|
2018-11-08 21:39:26 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->BeginDraw();
|
|
|
|
|
|
render_target_->Clear(clear_color_);
|
2018-11-19 17:56:17 +08:00
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
}
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
2018-11-12 20:46:54 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::EndDraw()
|
|
|
|
|
|
{
|
|
|
|
|
|
HRESULT hr = S_OK;
|
2018-11-23 14:55:03 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (!window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
hr = render_target_->EndDraw();
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (hr == D2DERR_RECREATE_TARGET)
|
|
|
|
|
|
{
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD> Direct3D <20>豸<EFBFBD><E8B1B8>ִ<EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>ε<EFBFBD><CEB5><EFBFBD>ʱ<EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD>Դ
|
|
|
|
|
|
DiscardResources();
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
}
|
2018-11-17 17:15:32 +08:00
|
|
|
|
}
|
2018-11-25 19:29:32 +08:00
|
|
|
|
|
|
|
|
|
|
if (debug_)
|
|
|
|
|
|
{
|
|
|
|
|
|
status_.duration = time::Now() - status_.start;
|
|
|
|
|
|
}
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
2018-11-17 17:15:32 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
void GraphicsDevice::ClearImageCache()
|
|
|
|
|
|
{
|
|
|
|
|
|
bitmap_cache_.clear();
|
|
|
|
|
|
}
|
2018-11-17 17:15:32 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
CpHwndRenderTarget const & GraphicsDevice::GetRenderTarget() const
|
2018-11-23 14:55:03 +08:00
|
|
|
|
{
|
|
|
|
|
|
return render_target_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
CpSolidColorBrush const & GraphicsDevice::GetSolidBrush() const
|
2018-11-23 14:55:03 +08:00
|
|
|
|
{
|
|
|
|
|
|
return solid_brush_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::CreateLayer(CpLayer& layer)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
layer = nullptr;
|
|
|
|
|
|
return render_target_->CreateLayer(&layer);
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::CreateSolidColorBrush(CpSolidColorBrush & brush) const
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
brush = nullptr;
|
|
|
|
|
|
return render_target_->CreateSolidColorBrush(
|
|
|
|
|
|
D2D1::ColorF(D2D1::ColorF::White),
|
|
|
|
|
|
&brush
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2018-11-19 17:56:17 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::DrawGeometry(
|
2019-01-08 19:30:02 +08:00
|
|
|
|
CpGeometry const& geometry,
|
2018-11-22 19:31:44 +08:00
|
|
|
|
Color const& stroke_color,
|
|
|
|
|
|
float stroke_width,
|
|
|
|
|
|
StrokeStyle stroke
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!solid_brush_ ||
|
|
|
|
|
|
!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
if (window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
solid_brush_->SetColor(stroke_color);
|
|
|
|
|
|
auto stroke_style = Factory::Instance()->GetStrokeStyle(stroke);
|
|
|
|
|
|
render_target_->DrawGeometry(
|
|
|
|
|
|
geometry.Get(),
|
|
|
|
|
|
solid_brush_.Get(),
|
|
|
|
|
|
stroke_width,
|
|
|
|
|
|
stroke_style.Get()
|
|
|
|
|
|
);
|
2018-11-23 14:55:03 +08:00
|
|
|
|
|
|
|
|
|
|
if (debug_)
|
|
|
|
|
|
++status_.primitives;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-20 01:20:06 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::FillGeometry(CpGeometry const & geometry, const Color & fill_color)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!solid_brush_ ||
|
|
|
|
|
|
!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-20 01:20:06 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (window_occluded_)
|
2018-11-20 01:20:06 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
solid_brush_->SetColor(fill_color);
|
|
|
|
|
|
render_target_->FillGeometry(
|
|
|
|
|
|
geometry.Get(),
|
|
|
|
|
|
solid_brush_.Get()
|
|
|
|
|
|
);
|
2018-11-23 14:55:03 +08:00
|
|
|
|
|
|
|
|
|
|
if (debug_)
|
|
|
|
|
|
++status_.primitives;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-18 20:26:41 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::DrawImage(SpImage const & image)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-18 20:26:41 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (!image->GetBitmap())
|
|
|
|
|
|
return S_OK;
|
2018-11-19 17:56:17 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (window_occluded_)
|
2018-11-18 20:26:41 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->DrawBitmap(
|
|
|
|
|
|
image->GetBitmap().Get(),
|
|
|
|
|
|
D2D1::RectF(0.f, 0.f, image->GetWidth(), image->GetHeight()),
|
|
|
|
|
|
opacity_,
|
|
|
|
|
|
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
|
|
|
|
|
image->GetCropRect()
|
|
|
|
|
|
);
|
2018-11-23 14:55:03 +08:00
|
|
|
|
|
|
|
|
|
|
if (debug_)
|
|
|
|
|
|
++status_.primitives;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT GraphicsDevice::DrawBitmap(
|
2019-01-08 19:30:02 +08:00
|
|
|
|
CpBitmap const& bitmap
|
2018-11-22 19:31:44 +08:00
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
if (window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
return S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
// Do not crop bitmap
|
|
|
|
|
|
auto rect = D2D1::RectF(0.f, 0.f, bitmap->GetSize().width, bitmap->GetSize().height);
|
|
|
|
|
|
render_target_->DrawBitmap(
|
|
|
|
|
|
bitmap.Get(),
|
|
|
|
|
|
rect,
|
|
|
|
|
|
opacity_,
|
|
|
|
|
|
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
|
|
|
|
|
rect
|
|
|
|
|
|
);
|
2018-11-23 14:55:03 +08:00
|
|
|
|
|
|
|
|
|
|
if (debug_)
|
|
|
|
|
|
++status_.primitives;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::DrawTextLayout(CpTextLayout const& text_layout)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!text_renderer_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-19 17:56:17 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (window_occluded_)
|
|
|
|
|
|
return S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
if (debug_)
|
|
|
|
|
|
++status_.primitives;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return text_layout->Draw(nullptr, text_renderer_.Get(), 0, 0);
|
|
|
|
|
|
}
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-25 15:00:15 +08:00
|
|
|
|
HRESULT GraphicsDevice::PushClip(const Matrix & clip_matrix, const Size & clip_size)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-19 17:56:17 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
return S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
render_target_->SetTransform(clip_matrix);
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->PushAxisAlignedClip(
|
2018-11-25 15:00:15 +08:00
|
|
|
|
D2D1::RectF(0, 0, clip_size.x, clip_size.y),
|
2018-11-22 19:31:44 +08:00
|
|
|
|
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
|
|
|
|
|
);
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::PopClip()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-19 17:56:17 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
return S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->PopAxisAlignedClip();
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::PushLayer(CpLayer const& layer, LayerProperties const& properties)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_ ||
|
|
|
|
|
|
!solid_brush_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
if (window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
return S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->PushLayer(
|
|
|
|
|
|
D2D1::LayerParameters(
|
|
|
|
|
|
properties.area,
|
|
|
|
|
|
nullptr,
|
|
|
|
|
|
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
|
|
|
|
|
|
D2D1::Matrix3x2F::Identity(),
|
|
|
|
|
|
properties.opacity,
|
|
|
|
|
|
solid_brush_.Get(),
|
|
|
|
|
|
D2D1_LAYER_OPTIONS_NONE
|
|
|
|
|
|
),
|
|
|
|
|
|
layer.Get()
|
|
|
|
|
|
);
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::PopLayer()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-19 17:56:17 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (window_occluded_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
return S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->PopLayer();
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT GraphicsDevice::GetSize(Size & size)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
auto rtsize = render_target_->GetSize();
|
2018-11-25 15:00:15 +08:00
|
|
|
|
size.x = rtsize.width;
|
|
|
|
|
|
size.y = rtsize.height;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::CreateBitmapFromFile(CpBitmap& bitmap, std::wstring const& file_path)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (render_target_ == nullptr)
|
2018-11-18 20:26:41 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
}
|
2018-11-18 20:26:41 +08:00
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
size_t hash_code = std::hash<std::wstring>{}(file_path);
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
|
|
|
|
|
|
{
|
|
|
|
|
|
bitmap = bitmap_cache_[hash_code];
|
2018-11-18 20:26:41 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
CpBitmap bitmap_tmp;
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT hr = Factory::Instance()->CreateBitmapFromFile(
|
|
|
|
|
|
bitmap,
|
|
|
|
|
|
render_target_,
|
|
|
|
|
|
file_path
|
|
|
|
|
|
);
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
|
|
|
|
|
|
}
|
2018-11-12 20:46:54 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::CreateBitmapFromResource(CpBitmap& bitmap, Resource const& res)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (render_target_ == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
}
|
2018-11-12 20:46:54 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
size_t hash_code = res.GetHashCode();
|
|
|
|
|
|
if (bitmap_cache_.find(hash_code) != bitmap_cache_.end())
|
|
|
|
|
|
{
|
|
|
|
|
|
bitmap = bitmap_cache_[hash_code];
|
|
|
|
|
|
return S_OK;
|
2018-11-12 02:10:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT hr = Factory::Instance()->CreateBitmapFromResource(
|
|
|
|
|
|
bitmap,
|
|
|
|
|
|
render_target_,
|
|
|
|
|
|
res
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (SUCCEEDED(hr))
|
2018-11-12 02:10:35 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
bitmap_cache_.insert(std::make_pair(hash_code, bitmap));
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
2018-11-12 20:46:54 +08:00
|
|
|
|
|
2019-01-08 19:30:02 +08:00
|
|
|
|
HRESULT GraphicsDevice::CreateBitmapRenderTarget(CpBitmapRenderTarget & brt)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
brt = nullptr;
|
|
|
|
|
|
return render_target_->CreateCompatibleRenderTarget(&brt);
|
|
|
|
|
|
}
|
2018-11-12 20:46:54 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::Resize(UINT32 width, UINT32 height)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->Resize(D2D1::SizeU(width, height));
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-18 20:26:41 +08:00
|
|
|
|
|
2018-11-25 15:00:15 +08:00
|
|
|
|
HRESULT GraphicsDevice::SetTransform(const Matrix & matrix)
|
2018-11-22 19:31:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-18 20:26:41 +08:00
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
render_target_->SetTransform(matrix);
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::SetOpacity(float opacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
opacity_ = opacity;
|
|
|
|
|
|
solid_brush_->SetOpacity(opacity);
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::SetTextStyle(
|
|
|
|
|
|
Color const& color,
|
|
|
|
|
|
bool has_outline,
|
|
|
|
|
|
Color const& outline_color,
|
|
|
|
|
|
float outline_width,
|
|
|
|
|
|
StrokeStyle outline_stroke
|
|
|
|
|
|
)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!text_renderer_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
auto stroke_style = Factory::Instance()->GetStrokeStyle(outline_stroke);
|
|
|
|
|
|
text_renderer_->SetTextStyle(
|
|
|
|
|
|
color,
|
|
|
|
|
|
has_outline,
|
|
|
|
|
|
outline_color,
|
|
|
|
|
|
outline_width,
|
|
|
|
|
|
stroke_style.Get()
|
|
|
|
|
|
);
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
void GraphicsDevice::SetClearColor(const Color& color)
|
|
|
|
|
|
{
|
|
|
|
|
|
clear_color_ = color;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::SetAntialiasMode(bool enabled)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
|
|
|
|
|
|
|
|
|
|
|
render_target_->SetAntialiasMode(
|
|
|
|
|
|
enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
|
|
|
|
|
|
);
|
|
|
|
|
|
antialias_ = enabled;
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::SetTextAntialiasMode(TextAntialias mode)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!render_target_)
|
|
|
|
|
|
return E_UNEXPECTED;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
text_antialias_ = mode;
|
|
|
|
|
|
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
|
|
|
|
|
switch (text_antialias_)
|
2018-11-08 21:39:26 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
case TextAntialias::Default:
|
|
|
|
|
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TextAntialias::ClearType:
|
|
|
|
|
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TextAntialias::GrayScale:
|
|
|
|
|
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TextAntialias::None:
|
|
|
|
|
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
}
|
2018-11-22 19:31:44 +08:00
|
|
|
|
render_target_->SetTextAntialiasMode(antialias_mode);
|
|
|
|
|
|
return S_OK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-23 14:55:03 +08:00
|
|
|
|
GraphicsDevice::Status const & GraphicsDevice::GetStatus() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return status_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
HRESULT GraphicsDevice::CreateResources(HWND hwnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
HRESULT hr = S_OK;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (!render_target_)
|
2018-11-12 02:10:35 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
RECT rc;
|
|
|
|
|
|
::GetClientRect(hwnd, &rc);
|
2018-11-21 19:24:18 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
D2D1_SIZE_U size = D2D1::SizeU(
|
|
|
|
|
|
rc.right - rc.left,
|
|
|
|
|
|
rc.bottom - rc.top
|
2018-11-21 19:24:18 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
hr = Factory::Instance()->CreateHwndRenderTarget(
|
|
|
|
|
|
render_target_,
|
|
|
|
|
|
D2D1::RenderTargetProperties(),
|
|
|
|
|
|
D2D1::HwndRenderTargetProperties(
|
|
|
|
|
|
hwnd,
|
|
|
|
|
|
size,
|
|
|
|
|
|
vsync_enabled_ ? D2D1_PRESENT_OPTIONS_NONE : D2D1_PRESENT_OPTIONS_IMMEDIATELY
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
2018-11-21 19:24:18 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
2018-11-21 19:24:18 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
SetAntialiasMode(antialias_);
|
|
|
|
|
|
SetTextAntialiasMode(text_antialias_);
|
2018-11-21 19:24:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
2018-11-12 02:10:35 +08:00
|
|
|
|
{
|
2018-11-22 19:31:44 +08:00
|
|
|
|
hr = render_target_->CreateSolidColorBrush(
|
|
|
|
|
|
D2D1::ColorF(D2D1::ColorF::White),
|
|
|
|
|
|
&solid_brush_
|
2018-11-12 02:10:35 +08:00
|
|
|
|
);
|
2018-11-22 19:31:44 +08:00
|
|
|
|
}
|
2018-11-12 02:10:35 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
if (SUCCEEDED(hr))
|
|
|
|
|
|
{
|
|
|
|
|
|
hr = Factory::Instance()->CreateTextRenderer(
|
|
|
|
|
|
text_renderer_,
|
2018-11-21 19:24:18 +08:00
|
|
|
|
render_target_,
|
2018-11-22 19:31:44 +08:00
|
|
|
|
solid_brush_
|
2018-11-12 02:10:35 +08:00
|
|
|
|
);
|
2018-11-08 21:39:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-11-22 19:31:44 +08:00
|
|
|
|
return hr;
|
|
|
|
|
|
}
|
2018-11-20 01:20:06 +08:00
|
|
|
|
|
2018-11-22 19:31:44 +08:00
|
|
|
|
void GraphicsDevice::DiscardResources()
|
|
|
|
|
|
{
|
|
|
|
|
|
// FIXME! Ӧ֪ͨ Game <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>нڵ<D0BD><DAB5><EFBFBD> device resources
|
|
|
|
|
|
fps_text_format_ = nullptr;
|
|
|
|
|
|
fps_text_layout_ = nullptr;
|
|
|
|
|
|
text_renderer_ = nullptr;
|
|
|
|
|
|
solid_brush_ = nullptr;
|
|
|
|
|
|
render_target_ = nullptr;
|
2018-11-08 21:39:26 +08:00
|
|
|
|
}
|
2018-11-22 19:31:44 +08:00
|
|
|
|
|
2018-11-08 21:39:26 +08:00
|
|
|
|
}
|