comparison render_sdl.c @ 2490:a0837ea61fda

Get static images working in GL mode
author Michael Pavone <pavone@retrodev.com>
date Wed, 17 Apr 2024 21:54:44 -0700
parents ccee8dccd9cc
children 88210caedc53
comparison
equal deleted inserted replaced
2489:fd04b139a73a 2490:a0837ea61fda
32 32
33 typedef struct { 33 typedef struct {
34 SDL_Window *win; 34 SDL_Window *win;
35 SDL_Renderer *renderer; 35 SDL_Renderer *renderer;
36 SDL_Texture *sdl_texture; 36 SDL_Texture *sdl_texture;
37 SDL_Texture **static_images;
37 window_close_handler on_close; 38 window_close_handler on_close;
38 uint32_t width; 39 uint32_t width;
39 uint32_t height; 40 uint32_t height;
41 uint8_t num_static;
40 #ifndef DISABLE_OPENGL 42 #ifndef DISABLE_OPENGL
41 SDL_GLContext *gl_context; 43 SDL_GLContext *gl_context;
42 uint32_t *texture_buf; 44 uint32_t *texture_buf;
43 uint32_t tex_width; 45 uint32_t tex_width;
44 uint32_t tex_height; 46 uint32_t tex_height;
45 GLuint gl_texture; 47 GLuint gl_texture;
48 GLuint *gl_static_images;
46 GLuint vshader; 49 GLuint vshader;
47 GLuint fshader; 50 GLuint fshader;
48 GLuint program; 51 GLuint program;
49 GLuint gl_buffers[2]; 52 GLuint gl_buffers[3];
53 GLuint image_buffer;
54 GLfloat *image_vertices;
50 GLint un_texture; 55 GLint un_texture;
51 GLint un_width; 56 GLint un_width;
52 GLint un_height; 57 GLint un_height;
53 GLint at_pos; 58 GLint at_pos;
59 GLint at_uv;
54 #endif 60 #endif
55 } extra_window; 61 } extra_window;
56 62
57 static SDL_Window *main_window; 63 static SDL_Window *main_window;
58 static extra_window *extras; 64 static extra_window *extras;
333 static GLfloat vertex_data_default[] = { 339 static GLfloat vertex_data_default[] = {
334 -1.0f, -1.0f, 340 -1.0f, -1.0f,
335 1.0f, -1.0f, 341 1.0f, -1.0f,
336 -1.0f, 1.0f, 342 -1.0f, 1.0f,
337 1.0f, 1.0f 343 1.0f, 1.0f
344 };
345
346 static GLfloat uvs[] = {
347 0.0f, 1.0f,
348 1.0f, 1.0f,
349 0.0f, 0.0f,
350 1.0f, 0.0f
338 }; 351 };
339 352
340 static GLfloat vertex_data[8]; 353 static GLfloat vertex_data[8];
341 354
342 static const GLushort element_data[] = {0, 1, 2, 3}; 355 static const GLushort element_data[] = {0, 1, 2, 3};
1549 extras[win_idx].tex_width = nearest_pow2(width); 1562 extras[win_idx].tex_width = nearest_pow2(width);
1550 extras[win_idx].tex_height = nearest_pow2(height); 1563 extras[win_idx].tex_height = nearest_pow2(height);
1551 } 1564 }
1552 extras[win_idx].texture_buf = calloc(extras[win_idx].tex_width * extras[win_idx].tex_height, sizeof(uint32_t)); 1565 extras[win_idx].texture_buf = calloc(extras[win_idx].tex_width * extras[win_idx].tex_height, sizeof(uint32_t));
1553 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, extras[win_idx].tex_width, extras[win_idx].tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, extras[win_idx].texture_buf); 1566 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, extras[win_idx].tex_width, extras[win_idx].tex_height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, extras[win_idx].texture_buf);
1554 glGenBuffers(2, extras[win_idx].gl_buffers); 1567 glGenBuffers(3, extras[win_idx].gl_buffers);
1555 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]); 1568 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]);
1556 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data_default), vertex_data_default, GL_STATIC_DRAW); 1569 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data_default), vertex_data_default, GL_STATIC_DRAW);
1557 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, extras[win_idx].gl_buffers[1]); 1570 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, extras[win_idx].gl_buffers[1]);
1558 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW); 1571 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_data), element_data, GL_STATIC_DRAW);
1572 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[2]);
1573 glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);
1559 extras[win_idx].vshader = load_shader("extra_window.v.glsl", GL_VERTEX_SHADER); 1574 extras[win_idx].vshader = load_shader("extra_window.v.glsl", GL_VERTEX_SHADER);
1560 extras[win_idx].fshader = load_shader("extra_window.f.glsl", GL_FRAGMENT_SHADER); 1575 extras[win_idx].fshader = load_shader("extra_window.f.glsl", GL_FRAGMENT_SHADER);
1561 extras[win_idx].program = glCreateProgram(); 1576 extras[win_idx].program = glCreateProgram();
1562 glAttachShader(program, extras[win_idx].vshader); 1577 glAttachShader(program, extras[win_idx].vshader);
1563 glAttachShader(program, extras[win_idx].fshader); 1578 glAttachShader(program, extras[win_idx].fshader);
1571 } 1586 }
1572 extras[win_idx].un_texture = glGetUniformLocation(program, "texture"); 1587 extras[win_idx].un_texture = glGetUniformLocation(program, "texture");
1573 extras[win_idx].un_width = glGetUniformLocation(program, "width"); 1588 extras[win_idx].un_width = glGetUniformLocation(program, "width");
1574 extras[win_idx].un_height = glGetUniformLocation(program, "height"); 1589 extras[win_idx].un_height = glGetUniformLocation(program, "height");
1575 extras[win_idx].at_pos = glGetAttribLocation(program, "pos"); 1590 extras[win_idx].at_pos = glGetAttribLocation(program, "pos");
1591 extras[win_idx].at_uv = glGetAttribLocation(program, "uv");
1576 } else { 1592 } else {
1577 sdl_renderer: 1593 sdl_renderer:
1578 #endif 1594 #endif
1579 extras[win_idx].renderer = SDL_CreateRenderer(extras[win_idx].win, -1, SDL_RENDERER_ACCELERATED); 1595 extras[win_idx].renderer = SDL_CreateRenderer(extras[win_idx].win, -1, SDL_RENDERER_ACCELERATED);
1580 if (!extras[win_idx].renderer) { 1596 if (!extras[win_idx].renderer) {
1620 SDL_DestroyWindow(extras[win_idx].win); 1636 SDL_DestroyWindow(extras[win_idx].win);
1621 1637
1622 extras[win_idx].win = NULL; 1638 extras[win_idx].win = NULL;
1623 } 1639 }
1624 1640
1625 SDL_Texture **static_images; 1641 #ifndef DISABLE_OPENGL
1626 uint8_t num_static; 1642 static void extra_draw_quad(extra_window *extra, GLuint texture, float width, float height)
1643 {
1644 glUseProgram(extra->program);
1645 glActiveTexture(GL_TEXTURE0);
1646 glBindTexture(GL_TEXTURE_2D, texture);
1647 glUniform1i(extra->un_texture, 0);
1648
1649 glUniform1f(extra->un_width, width);
1650 glUniform1f(extra->un_height, height);
1651
1652 glVertexAttribPointer(extra->at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
1653 glEnableVertexAttribArray(extra->at_pos);
1654
1655 glBindBuffer(GL_ARRAY_BUFFER, extra->gl_buffers[2]);
1656 glVertexAttribPointer(extra->at_uv, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0);
1657 glEnableVertexAttribArray(extra->at_uv);
1658
1659 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, extra->gl_buffers[1]);
1660 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0);
1661 }
1662 #endif
1663
1627 uint8_t render_static_image(uint8_t window, uint8_t *buffer, uint32_t size) 1664 uint8_t render_static_image(uint8_t window, uint8_t *buffer, uint32_t size)
1628 { 1665 {
1629 window -= FRAMEBUFFER_USER_START; 1666 window -= FRAMEBUFFER_USER_START;
1667 extra_window *extra = extras + window;
1630 uint32_t width, height; 1668 uint32_t width, height;
1631 uint32_t *pixels = load_png(buffer, size, &width, &height); 1669 uint32_t *pixels = load_png(buffer, size, &width, &height);
1632 if (!pixels) { 1670 if (!pixels) {
1633 return 0xFF; 1671 return 0xFF;
1634 } 1672 }
1635 uint8_t img_index = 0; 1673 uint8_t img_index = 0;
1636 if (!num_static) { 1674 if (!extra->num_static) {
1637 num_static = 8; 1675 extra->num_static = 8;
1638 static_images = calloc(num_static, sizeof(SDL_Texture*)); 1676 #ifndef DISABLE_OPENGL
1639 } 1677 if (render_gl) {
1640 for (; img_index < num_static; img_index++) 1678 extra->gl_static_images = calloc(extra->num_static, sizeof(GLuint));
1679 extra->image_vertices = malloc(sizeof(vertex_data_default));
1680 memcpy(extra->image_vertices, vertex_data_default, sizeof(vertex_data_default));
1681 SDL_GL_MakeCurrent(extra->win, extra->gl_context);
1682 glGenBuffers(1, &extra->image_buffer);
1683 glBindBuffer(GL_ARRAY_BUFFER, extra->image_buffer);
1684 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data_default), extra->image_vertices, GL_DYNAMIC_DRAW);
1685 } else
1686 #endif
1687 {
1688 extra->static_images = calloc(extra->num_static, sizeof(SDL_Texture*));
1689 }
1690 }
1691 for (; img_index < extra->num_static; img_index++)
1641 { 1692 {
1642 if (!static_images[img_index]) { 1693 #ifndef DISABLE_OPENGL
1694 if (render_gl) {
1695 if (!extra->gl_static_images[img_index]) {
1696 break;
1697 }
1698 } else
1699 #endif
1700 if (!extra->static_images[img_index]) {
1643 break; 1701 break;
1644 } 1702 }
1645 } 1703 }
1646 if (img_index == num_static) { 1704 if (img_index == extra->num_static) {
1647 num_static *= 2; 1705 extra->num_static *= 2;
1648 static_images = realloc(static_images, num_static * sizeof(SDL_Texture*)); 1706 #ifndef DISABLE_OPENGL
1649 } 1707 if (render_gl) {
1650 static_images[img_index] = SDL_CreateTexture(extras[window].renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height); 1708 extra->gl_static_images = realloc(extra->static_images, extra->num_static * sizeof(GLuint));
1651 SDL_UpdateTexture(static_images[img_index], NULL, pixels, sizeof(uint32_t) * width); 1709 } else
1710 #endif
1711 {
1712 extra->static_images = realloc(extra->static_images, extra->num_static * sizeof(SDL_Texture*));
1713 }
1714 }
1715 #ifndef DISABLE_OPENGL
1716 if (render_gl) {
1717 SDL_GL_MakeCurrent(extra->win, extra->gl_context);
1718
1719 glGenTextures(1, extra->gl_static_images + img_index);
1720 glBindTexture(GL_TEXTURE_2D, extra->gl_static_images[img_index]);
1721 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1722 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1723 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1724 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1725 //TODO: maybe make this respect the npot texture setting?
1726 glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, width, height, 0, SRC_FORMAT, GL_UNSIGNED_BYTE, pixels);
1727 } else
1728 #endif
1729 {
1730 extra->static_images[img_index] = SDL_CreateTexture(extra->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height);
1731 SDL_UpdateTexture(extra->static_images[img_index], NULL, pixels, sizeof(uint32_t) * width);
1732 }
1652 free(pixels); 1733 free(pixels);
1653 return img_index; 1734 return img_index;
1654 } 1735 }
1655 1736
1656 void render_draw_image(uint8_t window, uint8_t image, int x, int y, int width, int height) 1737 void render_draw_image(uint8_t window, uint8_t image, int x, int y, int width, int height)
1657 { 1738 {
1658 uint8_t win_idx = window - FRAMEBUFFER_USER_START; 1739 extra_window *extra = extras + window - FRAMEBUFFER_USER_START;
1659 if (extras[win_idx].renderer) { 1740 if (extra->renderer) {
1660 SDL_Rect dst = { 1741 SDL_Rect dst = {
1661 .x = x, 1742 .x = x,
1662 .y = y, 1743 .y = y,
1663 .w = width, 1744 .w = width,
1664 .h = height 1745 .h = height
1665 }; 1746 };
1666 SDL_RenderCopy(extras[win_idx].renderer, static_images[image], NULL, &dst); 1747 SDL_RenderCopy(extra->renderer, extra->static_images[image], NULL, &dst);
1667 } 1748 }
1668 #ifndef DISABLE_OPENGL 1749 #ifndef DISABLE_OPENGL
1669 else { 1750 else {
1670 //TODO: implement me 1751 memcpy(extra->image_vertices, vertex_data_default, sizeof(vertex_data_default));
1752 extra->image_vertices[0] = extra->image_vertices[4] = 2.0f * x / (float)extra->width - 1.0f;
1753 extra->image_vertices[2] = extra->image_vertices[6] = 2.0f * (x + width) / (float)extra->width - 1.0f;
1754 extra->image_vertices[1] = extra->image_vertices[3] = -2.0f * (y + height) / (float)extra->height + 1.0f;
1755 extra->image_vertices[5] = extra->image_vertices[7] = -2.0f * y / (float)extra->height + 1.0f;
1756
1757 SDL_GL_MakeCurrent(extra->win, extra->gl_context);
1758 glBindBuffer(GL_ARRAY_BUFFER, extra->image_buffer);
1759 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data_default), extra->image_vertices, GL_DYNAMIC_DRAW);
1760 extra_draw_quad(extra, extra->gl_static_images[image], 1.0f, 1.0f);
1671 } 1761 }
1672 #endif 1762 #endif
1673 } 1763 }
1674 1764
1675 void render_clear_window(uint8_t window, uint8_t r, uint8_t g, uint8_t b) 1765 void render_clear_window(uint8_t window, uint8_t r, uint8_t g, uint8_t b)
1940 #ifndef DISABLE_OPENGL 2030 #ifndef DISABLE_OPENGL
1941 else { 2031 else {
1942 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 2032 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1943 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 2033 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1944 2034
1945 glUseProgram(extras[win_idx].program);
1946 glActiveTexture(GL_TEXTURE0);
1947 glBindTexture(GL_TEXTURE_2D, extras[win_idx].gl_texture);
1948 glUniform1i(extras[win_idx].un_texture, 0);
1949
1950 glUniform1f(extras[win_idx].un_width, (float)extras[win_idx].width / (float)extras[win_idx].tex_width);
1951 glUniform1f(extras[win_idx].un_height, (float)extras[win_idx].height / (float)extras[win_idx].tex_height);
1952
1953 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]); 2035 glBindBuffer(GL_ARRAY_BUFFER, extras[win_idx].gl_buffers[0]);
1954 glVertexAttribPointer(extras[win_idx].at_pos, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat[2]), (void *)0); 2036 extra_draw_quad(
1955 glEnableVertexAttribArray(extras[win_idx].at_pos); 2037 extras + win_idx,
1956 2038 extras[win_idx].gl_texture,
1957 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, extras[win_idx].gl_buffers[1]); 2039 (float)extras[win_idx].width / (float)extras[win_idx].tex_width,
1958 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void *)0); 2040 (float)extras[win_idx].height / (float)extras[win_idx].tex_height
2041 );
1959 2042
1960 SDL_GL_SwapWindow(extras[win_idx].win); 2043 SDL_GL_SwapWindow(extras[win_idx].win);
1961 } 2044 }
1962 #endif 2045 #endif
1963 } 2046 }