use OpenGL legacy API for windows (faster than GDI)

This commit is contained in:
Carlos Aragones
2020-09-18 10:28:42 +02:00
parent 6a1e7e0b71
commit 09338014d1
11 changed files with 328 additions and 57 deletions

View File

@ -97,8 +97,8 @@ calc_dst_factor(SWindowData *window_data, uint32_t width, uint32_t height) {
//-------------------------------------
void
resize_dst(SWindowData *window_data, uint32_t width, uint32_t height) {
window_data->dst_offset_x = width * window_data->factor_x;
window_data->dst_offset_y = height * window_data->factor_y;
window_data->dst_width = width * window_data->factor_width;
window_data->dst_height = height * window_data->factor_height;
window_data->dst_offset_x = (uint32_t) (width * window_data->factor_x);
window_data->dst_offset_y = (uint32_t) (height * window_data->factor_y);
window_data->dst_width = (uint32_t) (width * window_data->factor_width);
window_data->dst_height = (uint32_t) (height * window_data->factor_height);
}

View File

@ -43,6 +43,7 @@ typedef struct {
uint32_t mod_keys;
bool is_active;
bool is_initialized;
bool close;
} SWindowData;

170
src/gl/MiniFB_GL.c Normal file
View File

@ -0,0 +1,170 @@
#if defined(USE_OPENGL_API)
#include "MiniFB_GL.h"
#if defined(_WIN32) || defined(WIN32)
#include <windows/WindowData_Win.h>
#endif
#include <gl/gl.h>
#include <stdlib.h>
//#define kUse_Clean_UP
#if defined(kUse_Clean_UP)
#define UseCleanUp(x) x
#else
#define UseCleanUp(x)
#endif
//-------------------------------------
void setup_pixel_format(HDC hDC);
//-------------------------------------
void
create_GL_context(SWindowData *window_data) {
SWindowData_Win *window_data_win;
window_data_win = (SWindowData_Win *) window_data->specific;
setup_pixel_format(window_data_win->hdc);
window_data_win->hGLRC = wglCreateContext(window_data_win->hdc);
wglMakeCurrent(window_data_win->hdc, window_data_win->hGLRC);
init_GL(window_data);
}
//-------------------------------------
void
setup_pixel_format(HDC hDC) {
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_SUPPORT_OPENGL | //
PFD_DRAW_TO_WINDOW | //
PFD_DOUBLEBUFFER, // support double-buffering
PFD_TYPE_RGBA, // color type
24, // preferred color depth
0, 0, 0, 0, 0, 0, // color and shift bits (ignored)
0, // no alpha buffer
0, // alpha bits (ignored)
0, // no accumulation buffer
0, 0, 0, 0, // accum bits (ignored)
24, // depth buffer
8, // no stencil buffer
0, // no auxiliary buffers
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0, // no layer, visible, damage masks
};
pixelFormat = ChoosePixelFormat(hDC, &pfd);
if (pixelFormat == 0) {
MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", MB_ICONERROR | MB_OK);
exit(1);
}
if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) {
MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", MB_ICONERROR | MB_OK);
exit(1);
}
}
#define TEXTURE0 0x84C0
//-------------------------------------
void
init_GL(SWindowData *window_data) {
SWindowData_Win *window_data_win;
window_data_win = (SWindowData_Win *) window_data->specific;
glViewport(0, 0, window_data->window_width, window_data->window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_data->window_width, window_data->window_height, 0, 2048, -2048);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &window_data_win->text_id);
//glActiveTexture(TEXTURE0);
glBindTexture(GL_TEXTURE_2D, window_data_win->text_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
UseCleanUp(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
UseCleanUp(glDisableClientState(GL_VERTEX_ARRAY));
UseCleanUp(glBindTexture(GL_TEXTURE_2D, 0));
}
//-------------------------------------
void
resize_GL(SWindowData *window_data) {
if(window_data->is_initialized) {
glViewport(0, 0, window_data->window_width, window_data->window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_data->window_width, window_data->window_height, 0, 2048, -2048);
glClear(GL_COLOR_BUFFER_BIT);
}
}
//-------------------------------------
void
redraw_GL(SWindowData *window_data, const void *pixels) {
float x, y, w, h;
SWindowData_Win *window_data_ex;
window_data_ex = (SWindowData_Win *) window_data->specific;
x = (float) window_data->dst_offset_x;
y = (float) window_data->dst_offset_y;
w = (float) window_data->dst_offset_x + window_data->dst_width;
h = (float) window_data->dst_offset_y + window_data->dst_height;
float vertices[] = {
x, y,
0, 0,
w, y,
1, 0,
x, h,
0, 1,
w, h,
1, 1,
};
glClear(GL_COLOR_BUFFER_BIT);
UseCleanUp(glBindTexture(GL_TEXTURE_2D, window_data_ex->text_id));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window_data->buffer_width, window_data->buffer_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, window_data->buffer_width, window_data->buffer_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
UseCleanUp(glEnableClientState(GL_VERTEX_ARRAY));
UseCleanUp(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), vertices);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), vertices + 2);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
UseCleanUp(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
UseCleanUp(glDisableClientState(GL_VERTEX_ARRAY));
UseCleanUp(glBindTexture(GL_TEXTURE_2D, 0));
SwapBuffers(window_data_ex->hdc);
}
#endif

12
src/gl/MiniFB_GL.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#if defined(USE_OPENGL_API)
#include "WindowData.h"
void create_GL_context(SWindowData *window_data);
void init_GL(SWindowData *window_data);
void redraw_GL(SWindowData *window_data, const void *pixels);
void resize_GL(SWindowData *window_data);
#endif

View File

@ -95,6 +95,7 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
}
[window makeKeyAndVisible];
window_data->is_initialized = true;
return (struct mfb_window *) window_data;
}
}

View File

@ -151,14 +151,17 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
#if defined(_DEBUG) || defined(DEBUG)
#if defined(USE_METAL_API)
NSLog(@"Window created using Metal API");
#else
NSLog(@"Window created using Cocoa API");
#endif
#endif
window_data->is_initialized = true;
return (struct mfb_window *) window_data;
}
}
}
//-------------------------------------

View File

@ -661,13 +661,17 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
#if defined(_DEBUG) || defined(DEBUG)
printf("Window created using Wayland API\n");
#endif
window_data->is_initialized = true;
return (struct mfb_window *) window_data;
out:
close(window_data_way->fd);
destroy(window_data);
return 0x0;
}

View File

@ -2,7 +2,9 @@
#include <MiniFB_internal.h>
#include <WindowData.h>
#include "WindowData_Win.h"
#if defined(USE_OPENGL_API)
#include "gl/MiniFB_GL.h"
#endif
#include <stdlib.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -29,31 +31,18 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message)
{
#if !defined(USE_OPENGL_API)
case WM_PAINT:
{
if (window_data && window_data->draw_buffer && window_data_win)
{
//if (window_data->dst_offset_x > 0) {
// BitBlt(window_data_win->hdc, 0, window_data->dst_offset_y, window_data->dst_offset_x, window_data->dst_height, 0, 0, 0, BLACKNESS);
//}
//if (window_data->dst_offset_y > 0) {
// BitBlt(window_data_win->hdc, 0, 0, window_data->window_width, window_data->dst_offset_y, 0, 0, 0, BLACKNESS);
//}
//uint32_t offsetY = window_data->dst_offset_y + window_data->dst_height;
//if (offsetY < window_data->window_height) {
// BitBlt(window_data_win->hdc, 0, offsetY, window_data->window_width, window_data->window_height - offsetY, 0, 0, 0, BLACKNESS);
//}
//uint32_t offsetX = window_data->dst_offset_x + window_data->dst_width;
//if (offsetX < window_data->window_width) {
// BitBlt(window_data_win->hdc, offsetX, window_data->dst_offset_y, window_data->window_width - offsetX, window_data->dst_height, 0, 0, 0, BLACKNESS);
//}
StretchDIBits(window_data_win->hdc, window_data->dst_offset_x, window_data->dst_offset_y, window_data->dst_width, window_data->dst_height, 0, 0, window_data->buffer_width, window_data->buffer_height, window_data->draw_buffer,
window_data_win->bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}
ValidateRect(hWnd, 0x0);
break;
}
#endif
case WM_DESTROY:
case WM_CLOSE:
@ -187,7 +176,12 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
window_data->window_width = LOWORD(lParam);
window_data->window_height = HIWORD(lParam);
resize_dst(window_data, LOWORD(lParam), HIWORD(lParam));
#if !defined(USE_OPENGL_API)
BitBlt(window_data_win->hdc, 0, 0, window_data->window_width, window_data->window_height, 0, 0, 0, BLACKNESS);
#else
resize_GL(window_data);
#endif
kCall(resize_func, window_data->dst_width, window_data->dst_height);
}
break;
@ -334,12 +328,17 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
ShowWindow(window_data_win->window, SW_NORMAL);
window_data_win->hdc = GetDC(window_data_win->window);
#if !defined(USE_OPENGL_API)
window_data_win->bitmapInfo = (BITMAPINFO *) calloc(1, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 3);
if(window_data_win->bitmapInfo == 0x0) {
free(window_data);
free(window_data_win);
return 0x0;
}
window_data_win->bitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
window_data_win->bitmapInfo->bmiHeader.biPlanes = 1;
window_data_win->bitmapInfo->bmiHeader.biBitCount = 32;
@ -350,12 +349,25 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
window_data_win->bitmapInfo->bmiColors[1].rgbGreen = 0xff;
window_data_win->bitmapInfo->bmiColors[2].rgbBlue = 0xff;
window_data_win->hdc = GetDC(window_data_win->window);
#else
create_GL_context(window_data);
#endif
window_data_win->timer = mfb_timer_create();
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
#if defined(_DEBUG) || defined(DEBUG)
#if defined(USE_OPENGL_API)
printf("Window created using OpenGL API\n");
#else
printf("Window created using GDI API\n");
#endif
#endif
window_data->is_initialized = true;
return (struct mfb_window *) window_data;
}
@ -385,11 +397,20 @@ mfb_update_ex(struct mfb_window *window, void *buffer, unsigned width, unsigned
window_data->buffer_height = height;
SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific;
#if !defined(USE_OPENGL_API)
window_data_win->bitmapInfo->bmiHeader.biWidth = window_data->buffer_width;
window_data_win->bitmapInfo->bmiHeader.biHeight = -(LONG) window_data->buffer_height;
InvalidateRect(window_data_win->window, 0x0, TRUE);
SendMessage(window_data_win->window, WM_PAINT, 0, 0);
#else
redraw_GL(window_data, buffer);
#endif
while (window_data->close == false && PeekMessage(&msg, window_data_win->window, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
@ -481,10 +502,18 @@ destroy_window_data(SWindowData *window_data) {
SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific;
window_data->draw_buffer = 0x0;
#if !defined(USE_OPENGL_API)
if (window_data_win->bitmapInfo != 0x0) {
free(window_data_win->bitmapInfo);
window_data_win->bitmapInfo = 0x0;
}
#else
if (window_data_win->hGLRC) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(window_data_win->hGLRC);
window_data_win->hGLRC = 0;
}
#endif
if (window_data_win->window != 0 && window_data_win->hdc != 0) {
ReleaseDC(window_data_win->window, window_data_win->hdc);
@ -492,11 +521,13 @@ destroy_window_data(SWindowData *window_data) {
}
window_data_win->window = 0;
window_data_win->hdc = 0;
window_data_win->bitmapInfo = 0x0;
window_data_win->hdc = 0;
mfb_timer_destroy(window_data_win->timer);
window_data_win->timer = 0x0;
window_data->close = true;
window_data->draw_buffer = 0x0;
window_data->close = true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -686,7 +717,6 @@ translate_key(unsigned int wParam, unsigned long lParam) {
bool
mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height) {
SWindowData *window_data = (SWindowData *) window;
SWindowData_Win *window_data_win = 0x0;
if(window_data == 0x0) {
return false;
@ -707,8 +737,12 @@ mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y
calc_dst_factor(window_data, window_data->window_width, window_data->window_height);
#if !defined(USE_OPENGL_API)
SWindowData_Win *window_data_win = 0x0;
window_data_win = (SWindowData_Win *) window_data->specific;
BitBlt(window_data_win->hdc, 0, 0, window_data->window_width, window_data->window_height, 0, 0, 0, BLACKNESS);
#endif
return true;
}

View File

@ -5,12 +5,16 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef struct {
HWND window;
WNDCLASS wc;
HDC hdc;
#if defined(USE_OPENGL_API)
HGLRC hGLRC;
uint32_t text_id;
#else
BITMAPINFO *bitmapInfo;
#endif
struct mfb_timer *timer;
bool mouse_inside;
} SWindowData_Win;

View File

@ -189,8 +189,11 @@ mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags)
mfb_set_keyboard_callback((struct mfb_window *) window_data, keyboard_default);
#if defined(_DEBUG) || defined(DEBUG)
printf("Window created using X11 API\n");
#endif
window_data->is_initialized = true;
return (struct mfb_window *) window_data;
}