Merge pull request #7403 from bparker06/gdi_imp

win32: Improvements to GDI drivers
This commit is contained in:
Twinaphex 2018-10-10 16:13:10 +02:00 committed by GitHub
commit 1fae526337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 218 additions and 32 deletions

View File

@ -27,6 +27,7 @@ typedef struct gdi
#endif #endif
HDC winDC; HDC winDC;
HDC memDC; HDC memDC;
HDC texDC;
HBITMAP bmp; HBITMAP bmp;
HBITMAP bmp_old; HBITMAP bmp_old;
unsigned video_width; unsigned video_width;
@ -35,4 +36,17 @@ typedef struct gdi
unsigned screen_height; unsigned screen_height;
} gdi_t; } gdi_t;
typedef struct gdi_texture
{
int width;
int height;
int active_width;
int active_height;
enum texture_filter_type type;
void* data;
HBITMAP bmp;
HBITMAP bmp_old;
} gdi_texture_t;
#endif #endif

View File

@ -837,18 +837,18 @@ LRESULT CALLBACK WndProcGDI(HWND hwnd, UINT message,
/* draw menu contents behind a gradient background */ /* draw menu contents behind a gradient background */
if (gdi && gdi->memDC) if (gdi && gdi->memDC)
{ {
RECT rect; /*RECT rect;
HBRUSH brush = CreateSolidBrush(RGB(1,81,127)); HBRUSH brush = CreateSolidBrush(RGB(1,81,127));
GetClientRect(hwnd, &rect); GetClientRect(hwnd, &rect);*/
StretchBlt(gdi->winDC, StretchBlt(gdi->winDC,
0, 0, 0, 0,
gdi->screen_width, gdi->screen_height, gdi->screen_width, gdi->screen_height,
gdi->memDC, 0, 0, gdi->video_width, gdi->video_height, SRCCOPY); gdi->memDC, 0, 0, gdi->video_width, gdi->video_height, SRCCOPY);
FillRect(gdi->memDC, &rect, brush); /*FillRect(gdi->memDC, &rect, brush);
DeleteObject(brush); DeleteObject(brush);*/
} }
} }
else else

View File

@ -16,6 +16,7 @@
*/ */
#include <retro_miscellaneous.h> #include <retro_miscellaneous.h>
#include <formats/image.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "../../config.h" #include "../../config.h"
@ -192,6 +193,9 @@ static bool gdi_gfx_frame(void *data, const void *frame,
HWND hwnd = win32_get_window(); HWND hwnd = win32_get_window();
BITMAPINFO *info; BITMAPINFO *info;
/* FIXME */
video_info->xmb_shadows_enable = false;
if (!frame || !frame_width || !frame_height) if (!frame || !frame_width || !frame_height)
return true; return true;
@ -414,9 +418,16 @@ static void gdi_gfx_free(void *data)
if (!gdi) if (!gdi)
return; return;
if (gdi->bmp)
DeleteObject(gdi->bmp);
if (gdi->texDC)
{
DeleteDC(gdi->texDC);
gdi->texDC = 0;
}
if (gdi->memDC) if (gdi->memDC)
{ {
DeleteObject(gdi->bmp);
DeleteDC(gdi->memDC); DeleteDC(gdi->memDC);
gdi->memDC = 0; gdi->memDC = 0;
} }
@ -532,12 +543,61 @@ static void gdi_set_video_mode(void *data, unsigned width, unsigned height,
video_context_driver_set_video_mode(&mode); video_context_driver_set_video_mode(&mode);
} }
static uintptr_t gdi_load_texture(void *video_data, void *data,
bool threaded, enum texture_filter_type filter_type)
{
struct texture_image *image = (struct texture_image*)data;
int size = image->width * image->height * sizeof(uint32_t);
gdi_texture_t *texture = NULL;
void *tmpdata = NULL;
if (!image || image->width > 2048 || image->height > 2048)
return 0;
texture = calloc(1, sizeof(*texture));
texture->width = image->width;
texture->height = image->height;
texture->active_width = image->width;
texture->active_height = image->height;
texture->data = calloc(1, texture->width * texture->height * sizeof(uint32_t));
texture->type = filter_type;
if (!texture->data)
{
free(texture);
return 0;
}
memcpy(texture->data, image->pixels, texture->width * texture->height * sizeof(uint32_t));
return (uintptr_t)texture;
}
static void gdi_unload_texture(void *data, uintptr_t handle)
{
struct gdi_texture *texture = (struct gdi_texture*)handle;
if (!texture)
return;
if (texture->data)
free(texture->data);
if (texture->bmp)
{
DeleteObject(texture->bmp);
texture->bmp = NULL;
}
free(texture);
}
static const video_poke_interface_t gdi_poke_interface = { static const video_poke_interface_t gdi_poke_interface = {
NULL, /* get_flags */ NULL, /* get_flags */
NULL, /* set_coords */ NULL, /* set_coords */
NULL, /* set_mvp */ NULL, /* set_mvp */
NULL, gdi_load_texture,
NULL, gdi_unload_texture,
gdi_set_video_mode, gdi_set_video_mode,
win32_get_refresh_rate, win32_get_refresh_rate,
NULL, NULL,

View File

@ -18,6 +18,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string/stdstring.h> #include <string/stdstring.h>
#include <encodings/utf.h> #include <encodings/utf.h>
#include <lists/string_list.h>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "../../config.h" #include "../../config.h"
@ -85,65 +86,116 @@ static void gdi_render_msg(
void *data, const char *msg, void *data, const char *msg,
const struct font_params *params) const struct font_params *params)
{ {
float x, y, scale; float x, y, scale, drop_mod, alpha, drop_alpha;
unsigned newX, newY, len; int i, drop_x, drop_y, msg_strlen;
unsigned newX, newY, newDropX, newDropY;
unsigned align; unsigned align;
unsigned red; unsigned red, green, blue;
unsigned green; unsigned drop_red, drop_green, drop_blue;
unsigned blue;
gdi_raster_t *font = (gdi_raster_t*)data; gdi_raster_t *font = (gdi_raster_t*)data;
unsigned width = video_info->width; unsigned width = video_info->width;
unsigned height = video_info->height; unsigned height = video_info->height;
SIZE textSize = {0};
struct string_list *msg_list = NULL;
if (!font || string_is_empty(msg) || !font->gdi) if (!font || string_is_empty(msg) || !font->gdi)
return; return;
if (params) if (params)
{ {
x = params->x; x = params->x;
y = params->y; y = params->y;
scale = params->scale; drop_x = params->drop_x;
align = params->text_align; drop_y = params->drop_y;
drop_mod = params->drop_mod;
drop_alpha = params->drop_alpha;
scale = params->scale;
align = params->text_align;
red = FONT_COLOR_GET_RED(params->color); red = FONT_COLOR_GET_RED(params->color);
green = FONT_COLOR_GET_GREEN(params->color); green = FONT_COLOR_GET_GREEN(params->color);
blue = FONT_COLOR_GET_BLUE(params->color); blue = FONT_COLOR_GET_BLUE(params->color);
alpha = FONT_COLOR_GET_ALPHA(params->color);
} }
else else
{ {
x = video_info->font_msg_pos_x; x = video_info->font_msg_pos_x;
y = video_info->font_msg_pos_y; y = video_info->font_msg_pos_y;
scale = 1.0f; drop_x = -2;
align = TEXT_ALIGN_LEFT; drop_y = -2;
red = video_info->font_msg_color_r * 255.0f; drop_mod = 0.3f;
green = video_info->font_msg_color_g * 255.0f; drop_alpha = 1.0f;
blue = video_info->font_msg_color_b * 255.0f; scale = 1.0f;
align = TEXT_ALIGN_LEFT;
red = video_info->font_msg_color_r * 255.0f;
green = video_info->font_msg_color_g * 255.0f;
blue = video_info->font_msg_color_b * 255.0f;
alpha = 255;
} }
len = utf8len(msg); msg_strlen = strlen(msg);
GetTextExtentPoint32(font->gdi->memDC, msg, msg_strlen, &textSize);
switch (align) switch (align)
{ {
case TEXT_ALIGN_LEFT: case TEXT_ALIGN_LEFT:
newX = x * width * scale; newX = x * width * scale;
newDropX = drop_x * width * scale;
break; break;
case TEXT_ALIGN_RIGHT: case TEXT_ALIGN_RIGHT:
newX = (x * width * scale) - len; newX = (x * width * scale) - textSize.cx;
newDropX = (drop_x * width * scale) - textSize.cx;
break; break;
case TEXT_ALIGN_CENTER: case TEXT_ALIGN_CENTER:
newX = (x * width * scale) - (len / 2); newX = (x * width * scale) - (textSize.cx / 2);
newDropX = (drop_x * width * scale) - (textSize.cx / 2);
break; break;
default: default:
newX = 0; newX = 0;
newDropX = 0;
break; break;
} }
newY = height - (y * height * scale); newY = height - (y * height * scale) - textSize.cy;
newDropY = height - (drop_y * height * scale) - textSize.cy;
font->gdi->bmp_old = (HBITMAP)SelectObject(font->gdi->memDC, font->gdi->bmp); font->gdi->bmp_old = (HBITMAP)SelectObject(font->gdi->memDC, font->gdi->bmp);
SetBkMode(font->gdi->memDC, TRANSPARENT); SetBkMode(font->gdi->memDC, TRANSPARENT);
msg_list = string_split(msg, "\n");
if (drop_x || drop_y)
{
float dark_alpha = drop_alpha;
drop_red = red * drop_mod * dark_alpha;
drop_green = green * drop_mod * dark_alpha;
drop_blue = blue * drop_mod * dark_alpha;
SetTextColor(font->gdi->memDC, RGB(drop_red, drop_green, drop_blue));
if (msg_list)
{
for (i = 0; i < msg_list->size; i++)
{
TextOut(font->gdi->memDC, newDropX, newDropY + (textSize.cy * i), msg_list->elems[i].data, utf8len(msg_list->elems[i].data));
}
}
}
SetTextColor(font->gdi->memDC, RGB(red, green, blue)); SetTextColor(font->gdi->memDC, RGB(red, green, blue));
TextOut(font->gdi->memDC, newX, newY, msg, len);
if (msg_list)
{
for (i = 0; i < msg_list->size; i++)
{
TextOut(font->gdi->memDC, newX, newY + (textSize.cy * i), msg_list->elems[i].data, utf8len(msg_list->elems[i].data));
}
string_list_free(msg_list);
}
SelectObject(font->gdi->memDC, font->gdi->bmp_old); SelectObject(font->gdi->memDC, font->gdi->bmp_old);
} }

View File

@ -16,17 +16,20 @@
#include <time.h> #include <time.h>
#include <clamping.h>
#include <queues/message_queue.h> #include <queues/message_queue.h>
#include <retro_miscellaneous.h> #include <retro_miscellaneous.h>
#include "../../config.def.h" #include "../../config.def.h"
#include "../../gfx/font_driver.h" #include "../../gfx/font_driver.h"
#include "../../gfx/video_driver.h" #include "../../gfx/video_driver.h"
#include "../../verbosity.h"
#include "../menu_driver.h" #include "../menu_driver.h"
#if defined(_WIN32) && !defined(_XBOX) #if defined(_WIN32) && !defined(_XBOX)
#include "../../gfx/common/win32_common.h" #include "../../gfx/common/win32_common.h"
#include "../../gfx/common/gdi_common.h"
#endif #endif
static void *menu_display_gdi_get_default_mvp(video_frame_info_t *video_info) static void *menu_display_gdi_get_default_mvp(video_frame_info_t *video_info)
@ -45,6 +48,63 @@ static void menu_display_gdi_blend_end(video_frame_info_t *video_info)
static void menu_display_gdi_draw(menu_display_ctx_draw_t *draw, static void menu_display_gdi_draw(menu_display_ctx_draw_t *draw,
video_frame_info_t *video_info) video_frame_info_t *video_info)
{ {
struct gdi_texture *texture = NULL;
gdi_t *gdi = (gdi_t*)video_driver_get_ptr(false);
BITMAPINFO info = {0};
if (!gdi || !draw || draw->x < 0 || draw->y < 0 || draw->width <= 1 || draw->height <= 1)
return;
texture = (struct gdi_texture*)draw->texture;
if (!texture || texture->width <= 1 || texture->height <= 1)
return;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biWidth = texture->width;
info.bmiHeader.biHeight = -texture->height;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biSizeImage = 0;
info.bmiHeader.biCompression = BI_RGB;
if (gdi->memDC)
{
BLENDFUNCTION blend = {0};
if (!gdi->texDC)
gdi->texDC = CreateCompatibleDC(gdi->winDC);
if (texture->bmp)
{
texture->bmp_old = SelectObject(gdi->texDC, texture->bmp);
}
else
{
/* scale texture data into a bitmap we can easily blit later */
texture->bmp = CreateCompatibleBitmap(gdi->winDC, draw->width, draw->height);
texture->bmp_old = SelectObject(gdi->texDC, texture->bmp);
StretchDIBits(gdi->texDC, 0, 0, draw->width, draw->height, 0, 0, texture->width, texture->height, texture->data, &info, DIB_RGB_COLORS, SRCCOPY);
}
gdi->bmp_old = SelectObject(gdi->memDC, gdi->bmp);
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.SourceConstantAlpha = 255;/*clamp_8bit(draw->coords->color[3] * 255.0f);*/
blend.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(gdi->memDC, draw->x, video_info->height - draw->height - draw->y, draw->width, draw->height, gdi->texDC, 0, 0, draw->width, draw->height, blend);
/*TransparentBlt(gdi->memDC, draw->x, video_info->height - draw->height - draw->y, draw->width, draw->height, gdi->texDC, 0, 0, draw->width, draw->height, 0);*/
/* To draw without blending: */
/*StretchBlt(gdi->memDC, draw->x, video_info->height - draw->height - draw->y, draw->width, draw->height, gdi->texDC, 0, 0, draw->width, draw->height, SRCCOPY);*/
SelectObject(gdi->memDC, gdi->bmp_old);
SelectObject(gdi->texDC, texture->bmp_old);
}
} }
static void menu_display_gdi_draw_pipeline(menu_display_ctx_draw_t *draw, static void menu_display_gdi_draw_pipeline(menu_display_ctx_draw_t *draw,
@ -80,7 +140,7 @@ static bool menu_display_gdi_font_init_first(
font_path, font_size, true, font_path, font_size, true,
is_threaded, is_threaded,
FONT_DRIVER_RENDER_GDI))) FONT_DRIVER_RENDER_GDI)))
return false; return false;
return true; return true;
} }