diff --git a/gfx/common/gdi_common.h b/gfx/common/gdi_common.h index 5abf72d35f..0b7872ab4d 100644 --- a/gfx/common/gdi_common.h +++ b/gfx/common/gdi_common.h @@ -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 diff --git a/gfx/common/win32_common.c b/gfx/common/win32_common.c index cdb1249668..f987602bfc 100644 --- a/gfx/common/win32_common.c +++ b/gfx/common/win32_common.c @@ -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: diff --git a/gfx/drivers/gdi_gfx.c b/gfx/drivers/gdi_gfx.c index 99f3118580..0b21886553 100644 --- a/gfx/drivers/gdi_gfx.c +++ b/gfx/drivers/gdi_gfx.c @@ -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); diff --git a/gfx/drivers_font/gdi_font.c b/gfx/drivers_font/gdi_font.c index 578b7705c2..e59d5b845a 100644 --- a/gfx/drivers_font/gdi_font.c +++ b/gfx/drivers_font/gdi_font.c @@ -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)