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,40 +610,46 @@ 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())
{
/* draw menu contents behind a gradient background */
if (gdi && gdi->memDC)
{
RECT rect;
TRIVERTEX vertex[2];
GRADIENT_RECT gRect;
GetClientRect(hwnd, &rect);
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;
StretchBlt(gdi->winDC,
0, 0,
gdi->screen_width, gdi->screen_height,
gdi->memDC, 0, 0, gdi->video_width, gdi->video_height, SRCCOPY);
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);
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);
}
EndPaint(hwnd, &ps);
break;
}
case WM_DROPFILES:

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,16 +206,34 @@ 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);
if (draw)
{
HDC winDC = GetDC(hwnd);
HDC memDC = CreateCompatibleDC(winDC);
HBITMAP bmp = CreateCompatibleBitmap(winDC, width, height);
gdi->screen_width = mode.width;
gdi->screen_height = mode.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);
@ -250,22 +267,15 @@ static bool gdi_gfx_frame(void *data, const void *frame,
else
info->bmiHeader.biCompression = BI_RGB;
StretchDIBits(memDC, 0, 0, width, height, 0, 0, width, height,
if (draw)
{
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);
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)