GDI: fix flickering of text

This commit is contained in:
Brad Parker 2017-08-22 23:39:05 -04:00
parent b2d9bad3a2
commit e3d68cd131
4 changed files with 133 additions and 90 deletions

View File

@ -21,6 +21,14 @@
typedef struct gdi
{
WNDCLASSEX wndclass;
HDC winDC;
HDC memDC;
HBITMAP bmp;
HBITMAP bmp_old;
unsigned video_width;
unsigned video_height;
unsigned screen_width;
unsigned screen_height;
} gdi_t;
#endif

View File

@ -21,6 +21,7 @@
#endif
#include "win32_common.h"
#include "gdi_common.h"
#include "../../frontend/frontend_driver.h"
#include "../../configuration.h"
#include "../../verbosity.h"
@ -609,41 +610,47 @@ LRESULT CALLBACK WndProcGDI(HWND hwnd, UINT message,
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
gdi_t *gdi = (gdi_t*)video_driver_get_ptr(false);
if (gdi && gdi->memDC)
{
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
#ifdef HAVE_MENU
if (menu_driver_is_alive() && !gdi_has_menu_frame())
{
RECT rect;
TRIVERTEX vertex[2];
GRADIENT_RECT gRect;
if (menu_driver_is_alive() && !gdi_has_menu_frame())
{
/* draw menu contents behind a gradient background */
if (gdi && gdi->memDC)
{
RECT rect;
GetClientRect(hwnd, &rect);
GetClientRect(hwnd, &rect);
StretchBlt(gdi->winDC,
0, 0,
gdi->screen_width, gdi->screen_height,
gdi->memDC, 0, 0, gdi->video_width, gdi->video_height, SRCCOPY);
vertex[0].x = rect.left;
vertex[0].y = rect.top;
vertex[0].Red = 1 << 8;
vertex[0].Green = 81 << 8;
vertex[0].Blue = 127 << 8;
vertex[0].Alpha = 0;
vertex[1].x = rect.right;
vertex[1].y = rect.bottom;
vertex[1].Red = 0;
vertex[1].Green = 1 << 8;
vertex[1].Blue = 33 << 8;
vertex[1].Alpha = 0;
gRect.LowerRight = 0;
gRect.UpperLeft = 1;
GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
}
HBRUSH brush = CreateSolidBrush(RGB(1,81,127));
FillRect(gdi->memDC, &rect, brush);
DeleteObject(brush);
}
}
else
#endif
{
/* draw video content */
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
EndPaint(hwnd, &ps);
break;
StretchBlt(gdi->winDC,
0, 0,
gdi->screen_width, gdi->screen_height,
gdi->memDC, 0, 0, gdi->video_width, gdi->video_height, SRCCOPY);
}
SelectObject(gdi->memDC, gdi->bmp_old);
}
break;
}
case WM_DROPFILES:
case WM_SYSCOMMAND:

View File

@ -160,7 +160,6 @@ static bool gdi_gfx_frame(void *data, const void *frame,
unsigned pitch, const char *msg, video_frame_info_t *video_info)
{
gfx_ctx_mode_t mode;
RECT rect;
const void *frame_to_copy = frame;
unsigned width = 0;
unsigned height = 0;
@ -207,66 +206,77 @@ static bool gdi_gfx_frame(void *data, const void *frame,
draw = false;
}
GetClientRect(hwnd, &rect);
if (hwnd && !gdi->winDC)
{
gdi->winDC = GetDC(hwnd);
gdi->memDC = CreateCompatibleDC(gdi->winDC);
gdi->video_width = width;
gdi->video_height = height;
gdi->bmp = CreateCompatibleBitmap(gdi->winDC, gdi->video_width, gdi->video_height);
}
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
if (gdi->video_width != width || gdi->video_height != height)
{
SelectObject(gdi->memDC, gdi->bmp_old);
DeleteObject(gdi->bmp);
gdi->video_width = width;
gdi->video_height = height;
gdi->bmp = CreateCompatibleBitmap(gdi->winDC, gdi->video_width, gdi->video_height);
gdi->bmp_old = (HBITMAP)SelectObject(gdi->memDC, gdi->bmp);
}
video_context_driver_get_video_size(&mode);
gdi->screen_width = mode.width;
gdi->screen_height = mode.height;
BITMAPINFO *info = (BITMAPINFO*)calloc(1, sizeof(*info) + (3 * sizeof(RGBQUAD)));
info->bmiHeader.biBitCount = bits;
info->bmiHeader.biWidth = pitch / (bits / 8);
info->bmiHeader.biHeight = -height;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) + (3 * sizeof(RGBQUAD));
info->bmiHeader.biSizeImage = 0;
if (bits == 16)
{
unsigned *masks = (unsigned*)info->bmiColors;
info->bmiHeader.biCompression = BI_BITFIELDS;
/* default 16-bit format on Windows is XRGB1555 */
if (frame_to_copy == gdi_menu_frame)
{
/* map RGB444 color bits for RGUI */
masks[0] = 0xF000;
masks[1] = 0x0F00;
masks[2] = 0x00F0;
}
else
{
/* map RGB565 color bits for core */
masks[0] = 0xF800;
masks[1] = 0x07E0;
masks[2] = 0x001F;
}
}
else
info->bmiHeader.biCompression = BI_RGB;
if (draw)
{
HDC winDC = GetDC(hwnd);
HDC memDC = CreateCompatibleDC(winDC);
HBITMAP bmp = CreateCompatibleBitmap(winDC, width, height);
BITMAPINFO *info = (BITMAPINFO*)calloc(1, sizeof(*info) + (3 * sizeof(RGBQUAD)));
HBITMAP bmp_old = (HBITMAP)SelectObject(memDC, bmp);
info->bmiHeader.biBitCount = bits;
info->bmiHeader.biWidth = pitch / (bits / 8);
info->bmiHeader.biHeight = -height;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) + (3 * sizeof(RGBQUAD));
info->bmiHeader.biSizeImage = 0;
if (bits == 16)
{
unsigned *masks = (unsigned*)info->bmiColors;
info->bmiHeader.biCompression = BI_BITFIELDS;
/* default 16-bit format on Windows is XRGB1555 */
if (frame_to_copy == gdi_menu_frame)
{
/* map RGB444 color bits for RGUI */
masks[0] = 0xF000;
masks[1] = 0x0F00;
masks[2] = 0x00F0;
}
else
{
/* map RGB565 color bits for core */
masks[0] = 0xF800;
masks[1] = 0x07E0;
masks[2] = 0x001F;
}
}
else
info->bmiHeader.biCompression = BI_RGB;
StretchDIBits(memDC, 0, 0, width, height, 0, 0, width, height,
StretchDIBits(gdi->memDC, 0, 0, width, height, 0, 0, width, height,
frame_to_copy, info, DIB_RGB_COLORS, SRCCOPY);
StretchBlt(winDC,
0, 0,
mode.width, mode.height,
memDC, 0, 0, width, height, SRCCOPY);
SelectObject(memDC, bmp_old);
DeleteObject(bmp);
DeleteDC(memDC);
ReleaseDC(hwnd, winDC);
free(info);
}
SelectObject(gdi->memDC, gdi->bmp_old);
free(info);
if (msg)
font_driver_render_msg(video_info, NULL, msg, NULL);
@ -330,6 +340,7 @@ static bool gdi_gfx_has_windowed(void *data)
static void gdi_gfx_free(void *data)
{
gdi_t *gdi = (gdi_t*)data;
HWND hwnd = win32_get_window();
if (gdi_menu_frame)
{
@ -340,6 +351,19 @@ static void gdi_gfx_free(void *data)
if (!gdi)
return;
if (gdi->memDC)
{
DeleteObject(gdi->bmp);
DeleteDC(gdi->memDC);
gdi->memDC = 0;
}
if (hwnd && gdi->winDC)
{
ReleaseDC(hwnd, gdi->winDC);
gdi->winDC = 0;
}
font_driver_free_osd();
video_context_driver_free();
free(gdi);

View File

@ -84,13 +84,11 @@ static void gdi_render_msg(
void *data, const char *msg,
const void *userdata)
{
HDC hdc;
float x, y, scale;
gdi_raster_t *font = (gdi_raster_t*)data;
unsigned newX, newY, len;
unsigned align;
const struct font_params *params = (const struct font_params*)userdata;
HWND hwnd = win32_get_window();
unsigned width = video_info->width;
unsigned height = video_info->height;
@ -133,12 +131,18 @@ static void gdi_render_msg(
}
newY = height - (y * height * scale);
hdc = GetDC(hwnd);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(255,255,255));
TextOut(hdc, newX, newY, msg, len);
ReleaseDC(hwnd, hdc);
uint64_t frame_count = 0;
bool is_alive = false;
bool is_focused = false;
video_driver_get_status(&frame_count, &is_alive, &is_focused);
font->gdi->bmp_old = (HBITMAP)SelectObject(font->gdi->memDC, font->gdi->bmp);
SetBkMode(font->gdi->memDC, TRANSPARENT);
SetTextColor(font->gdi->memDC, RGB(255,255,255));
TextOut(font->gdi->memDC, newX, newY, msg, len);
SelectObject(font->gdi->memDC, font->gdi->bmp_old);
}
static void gdi_font_flush_block(unsigned width, unsigned height, void* data)