Merge pull request #494 from dhrdlicka/feature/win_d2d
Direct2D refinements
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Rendering module for Microsoft Direct2D.
|
* Rendering module for Microsoft Direct2D.
|
||||||
*
|
*
|
||||||
* Version: @(#)win_d2d.cpp 1.0.5 2019/12/06
|
* Version: @(#)win_d2d.c 1.0.7 2019/12/13
|
||||||
*
|
*
|
||||||
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||||
*
|
*
|
||||||
@@ -18,18 +18,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <initguid.h>
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#define BITMAP WINDOWS_BITMAP
|
#define BITMAP WINDOWS_BITMAP
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#ifdef USE_D2D
|
|
||||||
#include <d2d1.h>
|
#include <d2d1.h>
|
||||||
#include <d2d1helper.h>
|
#include <d2d1helper.h>
|
||||||
#endif
|
|
||||||
#undef BITMAP
|
#undef BITMAP
|
||||||
|
|
||||||
#define PNG_DEBUG 0
|
|
||||||
#include <png.h>
|
|
||||||
|
|
||||||
#define HAVE_STDARG_H
|
#define HAVE_STDARG_H
|
||||||
#include "../86box.h"
|
#include "../86box.h"
|
||||||
#include "../device.h"
|
#include "../device.h"
|
||||||
@@ -41,29 +37,29 @@
|
|||||||
#include "win_d2d.h"
|
#include "win_d2d.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_D2D
|
|
||||||
static HWND d2d_hwnd, old_hwndMain;
|
static HWND d2d_hwnd, old_hwndMain;
|
||||||
static ID2D1Factory *d2d_factory;
|
static ID2D1Factory *d2d_factory;
|
||||||
static ID2D1HwndRenderTarget *d2d_hwndRT;
|
static ID2D1HwndRenderTarget *d2d_target;
|
||||||
static ID2D1BitmapRenderTarget *d2d_btmpRT;
|
static ID2D1Bitmap *d2d_buffer;
|
||||||
static ID2D1Bitmap *d2d_bitmap;
|
static int d2d_width, d2d_height, d2d_screen_width,
|
||||||
static int d2d_width, d2d_height, d2d_screen_width, d2d_screen_height, d2d_fs;
|
d2d_screen_height, d2d_fs;
|
||||||
static volatile int d2d_enabled = 0;
|
static volatile int d2d_enabled = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Pointers to the real functions. */
|
/* Pointers to the real functions. */
|
||||||
static HRESULT (*D2D1_CreateFactory)(D2D1_FACTORY_TYPE facType,
|
static HRESULT WINAPI (*D2D1_CreateFactory)(
|
||||||
|
D2D1_FACTORY_TYPE facType,
|
||||||
REFIID riid,
|
REFIID riid,
|
||||||
CONST D2D1_FACTORY_OPTIONS *pFacOptions,
|
const D2D1_FACTORY_OPTIONS *pFacOptions,
|
||||||
void **ppIFactory);
|
void **ppIFactory);
|
||||||
|
|
||||||
static dllimp_t d2d_imports[] = {
|
static dllimp_t d2d_imports[] = {
|
||||||
{ "D2D1CreateFactory", &D2D1_CreateFactory },
|
{ "D2D1CreateFactory", &D2D1_CreateFactory },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static volatile void *d2d_handle; /* handle to WinPcap DLL */
|
static volatile void *d2d_handle; /* handle to Direct2D DLL */
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_D2D_LOG
|
#ifdef ENABLE_D2D_LOG
|
||||||
@@ -86,7 +82,6 @@ d2d_log(const char *fmt, ...)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_D2D
|
|
||||||
static void
|
static void
|
||||||
d2d_stretch(float *w, float *h, float *x, float *y)
|
d2d_stretch(float *w, float *h, float *x, float *y)
|
||||||
{
|
{
|
||||||
@@ -154,49 +149,25 @@ d2d_stretch(float *w, float *h, float *x, float *y)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_D2D
|
|
||||||
static void
|
static void
|
||||||
d2d_blit(int x, int y, int y1, int y2, int w, int h)
|
d2d_blit(int x, int y, int y1, int y2, int w, int h)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
void *srcdata;
|
d2d_log("Direct2D: d2d_blit(x=%d, y=%d, y1=%d, y2=%d, w=%d, h=%d)\n",
|
||||||
int yy;
|
x, y, y1, y2, w, h);
|
||||||
D2D1_RECT_U rectU;
|
|
||||||
|
|
||||||
ID2D1Bitmap *fs_bitmap = 0;
|
|
||||||
ID2D1RenderTarget *RT;
|
|
||||||
|
|
||||||
float fs_x, fs_y;
|
|
||||||
float fs_w = w;
|
|
||||||
float fs_h = h;
|
|
||||||
|
|
||||||
d2d_log("Direct2D: d2d_blit(x=%d, y=%d, y1=%d, y2=%d, w=%d, h=%d)\n", x, y, y1, y2, w, h);
|
|
||||||
|
|
||||||
if (!d2d_enabled) {
|
if (!d2d_enabled) {
|
||||||
video_blit_complete();
|
video_blit_complete();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Detect double scanned mode and resize render target
|
if ((w != d2d_width || h != d2d_height) && !d2d_fs)
|
||||||
// appropriately for more clear picture
|
|
||||||
|
|
||||||
if (w != d2d_width || h != d2d_height)
|
|
||||||
{
|
{
|
||||||
if (d2d_fs)
|
D2D1_SIZE_U size = { .width = w, .height = h };
|
||||||
{
|
hr = ID2D1HwndRenderTarget_Resize(d2d_target, &size);
|
||||||
if (d2d_btmpRT)
|
|
||||||
{
|
|
||||||
d2d_btmpRT->Release();
|
|
||||||
d2d_btmpRT = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = d2d_hwndRT->CreateCompatibleRenderTarget(
|
|
||||||
D2D1::SizeF(w, h),
|
|
||||||
&d2d_btmpRT);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
@@ -204,17 +175,6 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h)
|
|||||||
d2d_height = h;
|
d2d_height = h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = d2d_hwndRT->Resize(D2D1::SizeU(w, h));
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
d2d_width = w;
|
|
||||||
d2d_height = h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y1 == y2) {
|
if (y1 == y2) {
|
||||||
video_blit_complete();
|
video_blit_complete();
|
||||||
@@ -226,85 +186,106 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Copy data directly from render_buffer to d2d_bitmap
|
/* Create a bitmap to store intermediate data */
|
||||||
|
if (d2d_buffer == NULL) {
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
D2D1_SIZE_U size = {
|
||||||
|
.width = render_buffer->w,
|
||||||
|
.height = render_buffer->h };
|
||||||
|
|
||||||
srcdata = malloc(h * w * 4);
|
D2D1_BITMAP_PROPERTIES bitmap_props = {
|
||||||
|
.pixelFormat = {
|
||||||
|
.format = DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||||
|
.alphaMode = D2D1_ALPHA_MODE_IGNORE
|
||||||
|
},
|
||||||
|
.dpiX = 96.0f,
|
||||||
|
.dpiY = 96.0f
|
||||||
|
};
|
||||||
|
|
||||||
for (yy = y1; yy < y2; yy++)
|
hr = ID2D1HwndRenderTarget_CreateBitmap(
|
||||||
{
|
d2d_target,
|
||||||
if ((y + yy) >= 0 && (y + yy) < render_buffer->h)
|
size,
|
||||||
{
|
NULL,
|
||||||
memcpy(
|
0,
|
||||||
(uint32_t *) &(((uint8_t *)srcdata)[yy * w * 4]),
|
&bitmap_props,
|
||||||
&(render_buffer->line[y + yy][x]),
|
&d2d_buffer);
|
||||||
w * 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy data from render_buffer */
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
D2D1_RECT_U rectU = {
|
||||||
|
.left = x,
|
||||||
|
.top = y + y1,
|
||||||
|
.right = x + w,
|
||||||
|
.bottom = y + y2
|
||||||
|
};
|
||||||
|
|
||||||
|
hr = ID2D1Bitmap_CopyFromMemory(
|
||||||
|
d2d_buffer,
|
||||||
|
&rectU,
|
||||||
|
&(render_buffer->line[y + y1][x]),
|
||||||
|
render_buffer->w << 2);
|
||||||
|
}
|
||||||
|
|
||||||
video_blit_complete();
|
video_blit_complete();
|
||||||
|
|
||||||
rectU = D2D1::RectU(0, 0, w, h);
|
/* Draw! */
|
||||||
hr = d2d_bitmap->CopyFromMemory(&rectU, srcdata, w * 4);
|
if (SUCCEEDED(hr)) {
|
||||||
|
D2D1_RECT_F destRect;
|
||||||
|
ID2D1HwndRenderTarget_BeginDraw(d2d_target);
|
||||||
|
|
||||||
// In fullscreen mode we first draw offscreen to an intermediate
|
if (d2d_fs) {
|
||||||
// BitmapRenderTarget, which then gets rendered to the actual
|
float fs_x = 0, fs_y = 0, fs_w = 0, fs_h = 0;
|
||||||
// HwndRenderTarget in order to implement different scaling modes
|
|
||||||
|
|
||||||
// In windowed mode we draw directly to the HwndRenderTarget
|
D2D1_COLOR_F black = {
|
||||||
|
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0 };
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
ID2D1HwndRenderTarget_Clear(
|
||||||
{
|
d2d_target,
|
||||||
RT = d2d_fs ? (ID2D1RenderTarget *) d2d_btmpRT : (ID2D1RenderTarget *) d2d_hwndRT;
|
&black
|
||||||
|
);
|
||||||
|
|
||||||
RT->BeginDraw();
|
|
||||||
|
|
||||||
RT->DrawBitmap(
|
|
||||||
d2d_bitmap,
|
|
||||||
D2D1::RectF(0, y1, w, y2),
|
|
||||||
1.0f,
|
|
||||||
D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR,
|
|
||||||
D2D1::RectF(0, y1, w, y2));
|
|
||||||
|
|
||||||
hr = RT->EndDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d2d_fs)
|
|
||||||
{
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = d2d_btmpRT->GetBitmap(&fs_bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
d2d_stretch(&fs_w, &fs_h, &fs_x, &fs_y);
|
d2d_stretch(&fs_w, &fs_h, &fs_x, &fs_y);
|
||||||
|
|
||||||
d2d_hwndRT->BeginDraw();
|
destRect = (D2D1_RECT_F) {
|
||||||
|
.left = fs_x,
|
||||||
|
.top = fs_y,
|
||||||
|
.right = fs_x + fs_w,
|
||||||
|
.bottom = fs_y + fs_h
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
destRect = (D2D1_RECT_F) {
|
||||||
|
.left = 0,
|
||||||
|
.top = 0,
|
||||||
|
.right = w,
|
||||||
|
.bottom = h
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
d2d_hwndRT->Clear(
|
D2D1_RECT_F srcRect = {
|
||||||
D2D1::ColorF(D2D1::ColorF::Black));
|
.left = x,
|
||||||
|
.top = y,
|
||||||
|
.right = x + w,
|
||||||
|
.bottom = y + h
|
||||||
|
};
|
||||||
|
|
||||||
d2d_hwndRT->DrawBitmap(
|
ID2D1HwndRenderTarget_DrawBitmap(
|
||||||
fs_bitmap,
|
d2d_target,
|
||||||
D2D1::RectF(fs_x, fs_y, fs_x + fs_w, fs_y + fs_h),
|
d2d_buffer,
|
||||||
|
&destRect,
|
||||||
1.0f,
|
1.0f,
|
||||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
||||||
D2D1::RectF(0, 0, w, h));
|
&srcRect);
|
||||||
|
|
||||||
hr = d2d_hwndRT->EndDraw();
|
hr = ID2D1HwndRenderTarget_EndDraw(d2d_target, NULL, NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
d2d_log("Direct2D: d2d_blit: error 0x%08lx\n", hr);
|
d2d_log("Direct2D: d2d_blit: error 0x%08lx\n", hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tidy up
|
|
||||||
free(srcdata);
|
|
||||||
srcdata = NULL;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -318,28 +299,21 @@ d2d_close(void)
|
|||||||
if (d2d_enabled)
|
if (d2d_enabled)
|
||||||
d2d_enabled = 0;
|
d2d_enabled = 0;
|
||||||
|
|
||||||
#ifdef USE_D2D
|
if (d2d_buffer)
|
||||||
if (d2d_bitmap)
|
|
||||||
{
|
{
|
||||||
d2d_bitmap->Release();
|
ID2D1Bitmap_Release(d2d_buffer);
|
||||||
d2d_bitmap = NULL;
|
d2d_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d2d_btmpRT)
|
if (d2d_target)
|
||||||
{
|
{
|
||||||
d2d_btmpRT->Release();
|
ID2D1HwndRenderTarget_Release(d2d_target);
|
||||||
d2d_btmpRT = NULL;
|
d2d_target = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (d2d_hwndRT)
|
|
||||||
{
|
|
||||||
d2d_hwndRT->Release();
|
|
||||||
d2d_hwndRT = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d2d_factory)
|
if (d2d_factory)
|
||||||
{
|
{
|
||||||
d2d_factory->Release();
|
ID2D1Factory_Release(d2d_factory);
|
||||||
d2d_factory = NULL;
|
d2d_factory = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,17 +331,14 @@ d2d_close(void)
|
|||||||
dynld_close((void *)d2d_handle);
|
dynld_close((void *)d2d_handle);
|
||||||
d2d_handle = NULL;
|
d2d_handle = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_D2D
|
|
||||||
static int
|
static int
|
||||||
d2d_init_common(int fs)
|
d2d_init_common(int fs)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
WCHAR title[200];
|
WCHAR title[200];
|
||||||
D2D1_HWND_RENDER_TARGET_PROPERTIES props;
|
|
||||||
|
|
||||||
d2d_log("Direct2D: d2d_init_common(fs=%d)\n", fs);
|
d2d_log("Direct2D: d2d_init_common(fs=%d)\n", fs);
|
||||||
|
|
||||||
@@ -400,39 +371,43 @@ d2d_init_common(int fs)
|
|||||||
plat_set_input(d2d_hwnd);
|
plat_set_input(d2d_hwnd);
|
||||||
|
|
||||||
SetFocus(d2d_hwnd);
|
SetFocus(d2d_hwnd);
|
||||||
SetWindowPos(d2d_hwnd, HWND_TOPMOST, 0, 0, d2d_screen_width, d2d_screen_height, SWP_SHOWWINDOW);
|
SetWindowPos(
|
||||||
|
d2d_hwnd, HWND_TOPMOST,
|
||||||
|
0, 0, d2d_screen_width, d2d_screen_height,
|
||||||
|
SWP_SHOWWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = D2D1_CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, __uuidof(ID2D1Factory),
|
hr = D2D1_CreateFactory(
|
||||||
NULL, reinterpret_cast <void **>(&d2d_factory));
|
D2D1_FACTORY_TYPE_MULTI_THREADED,
|
||||||
|
&IID_ID2D1Factory, NULL, (void **) &d2d_factory);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_props;
|
||||||
|
|
||||||
if (fs)
|
if (fs)
|
||||||
{
|
{
|
||||||
props = D2D1::HwndRenderTargetProperties(d2d_hwnd,
|
hwnd_props = (D2D1_HWND_RENDER_TARGET_PROPERTIES) {
|
||||||
D2D1::SizeU(d2d_screen_width, d2d_screen_height));
|
.hwnd = d2d_hwnd,
|
||||||
|
.pixelSize = {
|
||||||
|
.width = d2d_screen_width,
|
||||||
|
.height = d2d_screen_height
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// HwndRenderTarget will get resized appropriately by d2d_blit,
|
// HwndRenderTarget will get resized appropriately by d2d_blit,
|
||||||
// so it's fine to let D2D imply size of 0x0 for now
|
// so it's fine to let D2D imply size of 0x0 for now
|
||||||
props = D2D1::HwndRenderTargetProperties(hwndRender);
|
hwnd_props = (D2D1_HWND_RENDER_TARGET_PROPERTIES) {
|
||||||
|
.hwnd = hwndRender
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
D2D1_RENDER_TARGET_PROPERTIES target_props = { 0 };
|
||||||
{
|
|
||||||
hr = d2d_factory->CreateHwndRenderTarget(
|
|
||||||
D2D1::RenderTargetProperties(),
|
|
||||||
props,
|
|
||||||
&d2d_hwndRT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
hr = ID2D1Factory_CreateHwndRenderTarget(
|
||||||
{
|
d2d_factory, &target_props, &hwnd_props, &d2d_target);
|
||||||
// Create a bitmap for storing intermediate data
|
|
||||||
hr = d2d_hwndRT->CreateBitmap(
|
|
||||||
D2D1::SizeU(2048, 2048),
|
|
||||||
D2D1::BitmapProperties(D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE)),
|
|
||||||
&d2d_bitmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
@@ -460,19 +435,13 @@ d2d_init_common(int fs)
|
|||||||
|
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
d2d_init(HWND h)
|
d2d_init(HWND h)
|
||||||
{
|
{
|
||||||
d2d_log("Direct2D: d2d_init(h=0x%08lx)\n", h);
|
d2d_log("Direct2D: d2d_init(h=0x%08lx)\n", h);
|
||||||
|
|
||||||
#ifdef USE_D2D
|
|
||||||
return d2d_init_common(0);
|
return d2d_init_common(0);
|
||||||
#else
|
|
||||||
return(0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -480,12 +449,7 @@ int
|
|||||||
d2d_init_fs(HWND h)
|
d2d_init_fs(HWND h)
|
||||||
{
|
{
|
||||||
d2d_log("Direct2D: d2d_init_fs(h=0x%08lx)\n", h);
|
d2d_log("Direct2D: d2d_init_fs(h=0x%08lx)\n", h);
|
||||||
|
|
||||||
#ifdef USE_D2D
|
|
||||||
return d2d_init_common(1);
|
return d2d_init_common(1);
|
||||||
#else
|
|
||||||
return(0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Definitions for the Direct2D rendering module.
|
* Definitions for the Direct2D rendering module.
|
||||||
*
|
*
|
||||||
* Version: @(#)win_d2d.h 1.0.1 2019/10/12
|
* Version: @(#)win_d2d.h 1.0.2 2019/12/13
|
||||||
*
|
*
|
||||||
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||||
*
|
*
|
||||||
@@ -17,19 +17,10 @@
|
|||||||
#ifndef WIN_D2D_H
|
#ifndef WIN_D2D_H
|
||||||
# define WIN_D2D_H
|
# define WIN_D2D_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void d2d_close(void);
|
extern void d2d_close(void);
|
||||||
extern int d2d_init(HWND h);
|
extern int d2d_init(HWND h);
|
||||||
extern int d2d_init_fs(HWND h);
|
extern int d2d_init_fs(HWND h);
|
||||||
extern int d2d_pause(void);
|
extern int d2d_pause(void);
|
||||||
extern void d2d_enable(int enable);
|
extern void d2d_enable(int enable);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*WIN_D2D_H*/
|
#endif /*WIN_D2D_H*/
|
Reference in New Issue
Block a user