mirror of
https://github.com/libretro/beetle-psx-libretro.git
synced 2024-11-27 19:00:35 +00:00
Rewrite the GL renderer to remove the GL4.x requirements.
This commit is contained in:
parent
df1262004d
commit
90d7f63947
@ -2197,7 +2197,7 @@ static bool glsm_state_ctx_init(void *data)
|
||||
#else
|
||||
hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES2;
|
||||
#endif
|
||||
#else
|
||||
#else /* HAVE_OPENGLES */
|
||||
#ifdef CORE
|
||||
hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE;
|
||||
hw_render.version_major = 3;
|
||||
@ -2205,7 +2205,7 @@ static bool glsm_state_ctx_init(void *data)
|
||||
#else
|
||||
hw_render.context_type = RETRO_HW_CONTEXT_OPENGL;
|
||||
#endif
|
||||
#endif
|
||||
#endif /* HAVE_OPENGLES */
|
||||
hw_render.context_reset = params->context_reset;
|
||||
hw_render.context_destroy = params->context_destroy;
|
||||
hw_render.stencil = params->stencil;
|
||||
|
@ -241,7 +241,7 @@ void GlRenderer::draw()
|
||||
|
||||
this->command_buffer->program->uniform1ui("draw_semi_transparent", 0);
|
||||
|
||||
this->command_buffer->pre_bind();
|
||||
this->command_buffer->prepare_draw();
|
||||
|
||||
GLushort *opaque_triangle_indices =
|
||||
this->opaque_triangle_indices + this->opaque_triangle_index_pos + 1;
|
||||
@ -249,9 +249,9 @@ void GlRenderer::draw()
|
||||
INDEX_BUFFER_LEN - this->opaque_triangle_index_pos - 1;
|
||||
|
||||
if (opaque_triangle_len) {
|
||||
this->command_buffer->draw_indexed_no_bind(GL_TRIANGLES,
|
||||
opaque_triangle_indices,
|
||||
opaque_triangle_len);
|
||||
this->command_buffer->draw_indexed__raw(GL_TRIANGLES,
|
||||
opaque_triangle_indices,
|
||||
opaque_triangle_len);
|
||||
}
|
||||
|
||||
GLushort *opaque_line_indices =
|
||||
@ -260,9 +260,9 @@ void GlRenderer::draw()
|
||||
INDEX_BUFFER_LEN - this->opaque_line_index_pos - 1;
|
||||
|
||||
if (opaque_line_len) {
|
||||
this->command_buffer->draw_indexed_no_bind(GL_LINES,
|
||||
opaque_line_indices,
|
||||
opaque_line_len);
|
||||
this->command_buffer->draw_indexed__raw(GL_LINES,
|
||||
opaque_line_indices,
|
||||
opaque_line_len);
|
||||
}
|
||||
|
||||
if (this->semi_transparent_index_pos > 0) {
|
||||
@ -325,15 +325,16 @@ void GlRenderer::draw()
|
||||
unsigned len = it->last_index - cur_index;
|
||||
GLushort *indices = this->semi_transparent_indices + cur_index;
|
||||
|
||||
this->command_buffer->draw_indexed_no_bind(it->draw_mode,
|
||||
indices,
|
||||
len);
|
||||
this->command_buffer->draw_indexed__raw(it->draw_mode,
|
||||
indices,
|
||||
len);
|
||||
|
||||
cur_index = it->last_index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this->command_buffer->finish();
|
||||
this->command_buffer->finalize_draw__no_bind();
|
||||
|
||||
this->primitive_ordering = 0;
|
||||
this->opaque_triangle_index_pos = INDEX_BUFFER_LEN - 1;
|
||||
@ -463,7 +464,6 @@ void GlRenderer::upload_textures(uint16_t top_left[2],
|
||||
Framebuffer _fb = Framebuffer(this->fb_out);
|
||||
|
||||
this->image_load_buffer->draw(GL_TRIANGLE_STRIP);
|
||||
this->image_load_buffer->swap();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, this->command_polygon_mode);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
@ -510,7 +510,6 @@ void GlRenderer::upload_vram_window(uint16_t top_left[2],
|
||||
Framebuffer _fb = Framebuffer(this->fb_out);
|
||||
|
||||
this->image_load_buffer->draw(GL_TRIANGLE_STRIP);
|
||||
this->image_load_buffer->swap();
|
||||
glPolygonMode(GL_FRONT_AND_BACK, this->command_polygon_mode);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
@ -749,7 +748,6 @@ void GlRenderer::finalize_frame()
|
||||
this->output_buffer->program->uniform1ui( "internal_upscaling",
|
||||
this->internal_upscaling);
|
||||
this->output_buffer->draw(GL_TRIANGLE_STRIP);
|
||||
this->output_buffer->swap();
|
||||
}
|
||||
|
||||
// Hack: copy fb_out back into fb_texture at the end of every
|
||||
@ -779,7 +777,6 @@ void GlRenderer::finalize_frame()
|
||||
|
||||
|
||||
this->image_load_buffer->draw(GL_TRIANGLE_STRIP);
|
||||
this->image_load_buffer->swap();
|
||||
}
|
||||
|
||||
// Cleanup OpenGL context before returning to the frontend
|
||||
@ -869,7 +866,6 @@ void GlRenderer::vertex_preprocessing(CommandVertex *v,
|
||||
|
||||
if (buffer_full) {
|
||||
this->draw();
|
||||
this->command_buffer->swap();
|
||||
}
|
||||
|
||||
int16_t z = this->primitive_ordering;
|
||||
@ -910,8 +906,11 @@ void GlRenderer::push_quad(CommandVertex v[4],
|
||||
|
||||
this->vertex_preprocessing(v, 4, GL_TRIANGLES, stm);
|
||||
|
||||
// The diagonal is duplicated
|
||||
static const GLushort indices[6] = {0, 1, 2, 1, 2, 3};
|
||||
// The diagonal is duplicated. I originally used "1, 2, 1, 2" to
|
||||
// duplicate the diagonal but I believe it was incorrect because of
|
||||
// the OpenGL filling convention. At least it's what TinyTiger told
|
||||
// me...
|
||||
static const GLushort indices[6] = {0, 1, 2, 2, 1, 3};
|
||||
|
||||
unsigned index = this->command_buffer->next_index();
|
||||
|
||||
@ -1048,13 +1047,26 @@ void GlRenderer::copy_rect( uint16_t source_top_left[2],
|
||||
GLsizei w = (GLsizei) dimensions[0] * (GLsizei) upscale;
|
||||
GLsizei h = (GLsizei) dimensions[1] * (GLsizei) upscale;
|
||||
|
||||
// XXX CopyImageSubData gives undefined results if the source
|
||||
// and target area overlap, this should be handled
|
||||
// explicitely
|
||||
/* TODO - OpenGL 4.3 and GLES 3.2 requirement! FIXME! */
|
||||
glCopyImageSubData( this->fb_out->id, GL_TEXTURE_2D, 0, src_x, src_y, 0,
|
||||
this->fb_out->id, GL_TEXTURE_2D, 0, dst_x, dst_y, 0,
|
||||
w, h, 1 );
|
||||
GLuint fb;
|
||||
|
||||
glGenFramebuffers(1, &fb);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb);
|
||||
glFramebufferTexture(GL_READ_FRAMEBUFFER,
|
||||
GL_COLOR_ATTACHMENT0,
|
||||
this->fb_out->id,
|
||||
0);
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
// Can I bind the same texture to the framebuffer and
|
||||
// GL_TEXTURE_2D? Something tells me this is undefined
|
||||
// behaviour. I could use glReadPixels and glWritePixels instead
|
||||
// or something like that.
|
||||
glBindTexture(GL_TEXTURE_2D, this->fb_out->id);
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, dst_x, dst_y, src_x, src_y, w, h);
|
||||
|
||||
glDeleteFramebuffers(1, &fb);
|
||||
|
||||
get_error();
|
||||
}
|
||||
|
@ -30,8 +30,10 @@ const uint16_t VRAM_WIDTH_PIXELS = 1024;
|
||||
const uint16_t VRAM_HEIGHT = 512;
|
||||
const size_t VRAM_PIXELS = (size_t) VRAM_WIDTH_PIXELS * (size_t) VRAM_HEIGHT;
|
||||
|
||||
/// How many vertices we buffer before forcing a draw
|
||||
static const unsigned int VERTEX_BUFFER_LEN = 0x8000;
|
||||
/// How many vertices we buffer before forcing a draw. Since the
|
||||
/// indexes are stored on 16bits we need to make sure that the length
|
||||
/// multiplied by 3 (for triple buffering) doesn't overflow 0xffff.
|
||||
static const unsigned int VERTEX_BUFFER_LEN = 0x4000;
|
||||
/// Maximum number of indices for a vertex buffer. Since quads have
|
||||
/// two duplicated vertices it can be up to 3/2 the vertex buffer
|
||||
/// length
|
||||
@ -49,7 +51,7 @@ struct DrawConfig {
|
||||
|
||||
struct CommandVertex {
|
||||
/// Position in PlayStation VRAM coordinates
|
||||
float position[4];
|
||||
float position[4];
|
||||
/// RGB color, 8bits per component
|
||||
uint8_t color[3];
|
||||
/// Texture coordinates within the page
|
||||
|
@ -4,58 +4,17 @@
|
||||
#include <glsm/glsmsym.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // size_t
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
//#include <unistd.h>
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <cassert>
|
||||
|
||||
#include "vertex.h"
|
||||
#include "program.h"
|
||||
#include "error.h"
|
||||
|
||||
template<typename T>
|
||||
struct Storage {
|
||||
// Fence used to make sure we're not writing to the buffer while
|
||||
// it's being used.
|
||||
GLsync fence;
|
||||
// Offset in the main buffer
|
||||
unsigned offset;
|
||||
|
||||
Storage()
|
||||
:fence(NULL), offset(0)
|
||||
{
|
||||
}
|
||||
|
||||
Storage(unsigned offset)
|
||||
:fence(NULL), offset(offset)
|
||||
{
|
||||
}
|
||||
|
||||
~Storage() {
|
||||
if (this->fence) {
|
||||
glDeleteSync(this->fence);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the buffer to be ready for reuse
|
||||
void sync() {
|
||||
if (this->fence) {
|
||||
glWaitSync(this->fence, 0, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(this->fence);
|
||||
this->fence = NULL;
|
||||
get_error();
|
||||
}
|
||||
}
|
||||
|
||||
void create_fence() {
|
||||
void *fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
this->fence = reinterpret_cast<GLsync>(fence);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class DrawBuffer
|
||||
{
|
||||
@ -68,20 +27,19 @@ public:
|
||||
VertexArrayObject* vao;
|
||||
/// Program used to draw this buffer
|
||||
Program* program;
|
||||
/// Persistently mapped buffer (using ARB_buffer_storage)
|
||||
/// Currently mapped buffer range (write-only)
|
||||
T *map;
|
||||
/// Use triple buffering
|
||||
Storage<T> buffers[3];
|
||||
unsigned active_buffer;
|
||||
|
||||
/// Index one-past the last element stored in `active`
|
||||
unsigned active_next_index;
|
||||
/// Index of the first element of the current command in `active`
|
||||
unsigned active_command_index;
|
||||
/// Number of elements T that `active` and `backed` can hold
|
||||
/// Number of elements T mapped at once in `map`
|
||||
size_t capacity;
|
||||
/// Index one-past the last element stored in `map`, relative to
|
||||
/// the first element in `map`
|
||||
size_t map_index;
|
||||
/// Absolute offset of the 1st mapped element in the current
|
||||
/// buffer relative to the beginning of the GL storage.
|
||||
size_t map_start;
|
||||
|
||||
DrawBuffer(size_t capacity, Program* program)
|
||||
:map(NULL)
|
||||
{
|
||||
VertexArrayObject* vao = new VertexArrayObject();
|
||||
|
||||
@ -97,36 +55,22 @@ public:
|
||||
// Create and map the buffer
|
||||
this->bind();
|
||||
size_t element_size = sizeof(T);
|
||||
// We double buffer so we allocate a storage twise as big
|
||||
GLsizeiptr storage_size = (GLsizeiptr) (this->capacity * element_size * 3);
|
||||
// We allocate enough space for 3 times the buffer space and
|
||||
// we only remap one third of it at a time
|
||||
GLsizeiptr storage_size = this->capacity * element_size * 3;
|
||||
|
||||
glBufferStorage(GL_ARRAY_BUFFER,
|
||||
storage_size,
|
||||
NULL,
|
||||
GL_MAP_WRITE_BIT |
|
||||
GL_MAP_PERSISTENT_BIT |
|
||||
GL_MAP_COHERENT_BIT);
|
||||
// Since we store indexes in unsigned shorts we want to make
|
||||
// sure the entire buffer is indexable.
|
||||
assert(this->capacity * 3 <= 0xffff);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, storage_size, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
this->bind_attributes();
|
||||
|
||||
void *m = glMapBufferRange(GL_ARRAY_BUFFER,
|
||||
0,
|
||||
storage_size,
|
||||
GL_MAP_WRITE_BIT |
|
||||
GL_MAP_PERSISTENT_BIT |
|
||||
GL_MAP_FLUSH_EXPLICIT_BIT |
|
||||
GL_MAP_COHERENT_BIT);
|
||||
this->map_index = 0;
|
||||
this->map_start = 0;
|
||||
|
||||
this->map = reinterpret_cast<T*>(m);
|
||||
|
||||
this->buffers[0] = Storage<T>(0);
|
||||
this->buffers[1] = Storage<T>(this->capacity);
|
||||
this->buffers[2] = Storage<T>(this->capacity * 2);
|
||||
|
||||
this->active_buffer = 0;
|
||||
|
||||
this->active_next_index = 0;
|
||||
this->active_command_index = 0;
|
||||
this->map__no_bind();
|
||||
|
||||
get_error();
|
||||
}
|
||||
@ -135,10 +79,7 @@ public:
|
||||
{
|
||||
this->bind();
|
||||
|
||||
this->buffers[1].sync();
|
||||
this->buffers[2].sync();
|
||||
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
this->unmap__no_bind();
|
||||
|
||||
glDeleteBuffers(1, &this->id);
|
||||
|
||||
@ -153,12 +94,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
struct Storage<T> *get_active_buffer()
|
||||
{
|
||||
return &this->buffers[this->active_buffer];
|
||||
}
|
||||
|
||||
/* fn bind_attributes(&self)-> Result<(), Error> { */
|
||||
void bind_attributes()
|
||||
{
|
||||
this->vao->bind();
|
||||
@ -170,20 +105,6 @@ public:
|
||||
|
||||
GLint element_size = (GLint) sizeof( T );
|
||||
|
||||
/*
|
||||
let index =
|
||||
match self.program.find_attribute(attr.name) {
|
||||
Ok(i) => i,
|
||||
// Don't error out if the shader doesn't use this
|
||||
// attribute, it could be caused by shader
|
||||
// optimization if the attribute is unused for
|
||||
// some reason.
|
||||
Err(Error::InvalidValue) => continue,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
//speculative: attribs enabled on VAO=0 (disabled) get applied to the VAO when created initially
|
||||
//as a core, we don't control the state entirely at this point. frontend may have enabled attribs.
|
||||
//we need to make sure they're all disabled before then re-enabling the attribs we want
|
||||
@ -241,22 +162,60 @@ public:
|
||||
get_error();
|
||||
}
|
||||
|
||||
unsigned next_index() {
|
||||
return this->active_next_index;
|
||||
// Map the buffer for write-only access
|
||||
void map__no_bind()
|
||||
{
|
||||
size_t element_size = sizeof(T);
|
||||
GLsizeiptr buffer_size = this->capacity * element_size;
|
||||
GLintptr offset_bytes;
|
||||
void *m;
|
||||
|
||||
this->bind();
|
||||
|
||||
// If we're already mapped something's wrong
|
||||
assert(this->map == NULL);
|
||||
|
||||
if (this->map_start > 2 * this->capacity) {
|
||||
// We don't have enough room left to remap `capacity`,
|
||||
// start back from the beginning of the buffer.
|
||||
this->map_start = 0;
|
||||
}
|
||||
|
||||
offset_bytes = this->map_start * element_size;
|
||||
|
||||
printf("Remap %lu %lu\n", this->capacity, this->map_start);
|
||||
|
||||
m = glMapBufferRange(GL_ARRAY_BUFFER,
|
||||
offset_bytes,
|
||||
buffer_size,
|
||||
GL_MAP_WRITE_BIT |
|
||||
GL_MAP_INVALIDATE_RANGE_BIT);
|
||||
|
||||
get_error();
|
||||
|
||||
// Just in case...
|
||||
assert(m != NULL);
|
||||
|
||||
this->map = reinterpret_cast<T *>(m);
|
||||
}
|
||||
|
||||
/// Swap the active and backed buffers
|
||||
void swap() {
|
||||
this->get_active_buffer()->create_fence();
|
||||
// Unmap the active buffer
|
||||
void unmap__no_bind()
|
||||
{
|
||||
assert(this->map != NULL);
|
||||
|
||||
if (++this->active_buffer > 2) {
|
||||
this->active_buffer = 0;
|
||||
}
|
||||
this->bind();
|
||||
|
||||
this->get_active_buffer()->sync();
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
|
||||
this->active_next_index = 0;
|
||||
this->active_command_index = 0;
|
||||
this->map = NULL;
|
||||
}
|
||||
|
||||
/// Returns the index of the next item to be inserted in
|
||||
/// `map`. Can be used to build an index buffer for indexed draws.
|
||||
size_t next_index()
|
||||
{
|
||||
return this->map_start + this->map_index;
|
||||
}
|
||||
|
||||
void enable_attribute(const char* attr)
|
||||
@ -289,16 +248,10 @@ public:
|
||||
get_error();
|
||||
}
|
||||
|
||||
/// Return true if `map` is empty
|
||||
bool empty()
|
||||
{
|
||||
return this->active_next_index == this->active_command_index;
|
||||
}
|
||||
|
||||
/// Called when the current batch is completed (the draw calls
|
||||
/// have been done and we won't reference that data anymore)
|
||||
void finish()
|
||||
{
|
||||
this->active_command_index = this->active_next_index;
|
||||
return this->map_index == 0;
|
||||
}
|
||||
|
||||
/// Bind the buffer to the current VAO
|
||||
@ -307,69 +260,84 @@ public:
|
||||
glBindBuffer(GL_ARRAY_BUFFER, this->id);
|
||||
}
|
||||
|
||||
/// Push new vertices in the storage. If `n` is greater than
|
||||
/// `remaining_capacity` this function crashes, it's up to the
|
||||
/// caller to make sure there's enough room left.
|
||||
void push_slice(T slice[], size_t n)
|
||||
{
|
||||
if (n > this->remaining_capacity() ) {
|
||||
printf("DrawBuffer::push_slice() - Out of memory \n");
|
||||
return;
|
||||
}
|
||||
assert(n <= this->remaining_capacity());
|
||||
assert(this->map != NULL);
|
||||
|
||||
struct Storage<T> *buffer = this->get_active_buffer();
|
||||
|
||||
memcpy(this->map + buffer->offset + this->active_next_index,
|
||||
memcpy(this->map + this->map_index,
|
||||
slice,
|
||||
n * sizeof(T));
|
||||
|
||||
this->active_next_index += n;
|
||||
this->map_index += n;
|
||||
}
|
||||
|
||||
/// Prepares the buffer for a draw command. We have to bind the
|
||||
/// VAO, the program and unmap the buffer.
|
||||
void prepare_draw()
|
||||
{
|
||||
this->vao->bind();
|
||||
this->program->bind();
|
||||
// I don't need to bind this to draw (it's captured by the
|
||||
// VAO) but I need it to map/unmap the storage.
|
||||
this->bind();
|
||||
|
||||
this->unmap__no_bind();
|
||||
}
|
||||
|
||||
/// Finalize the current buffer data and remap a fresh slice of
|
||||
/// the storage.
|
||||
void finalize_draw__no_bind()
|
||||
{
|
||||
this->map_start += this->map_index;
|
||||
this->map_index = 0;
|
||||
|
||||
this->map__no_bind();
|
||||
}
|
||||
|
||||
void draw(GLenum mode)
|
||||
{
|
||||
printf("Draw %lu\n", this->map_index);
|
||||
|
||||
if (this->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->vao->bind();
|
||||
this->program->bind();
|
||||
|
||||
struct Storage<T> *buffer = this->get_active_buffer();
|
||||
|
||||
unsigned start = buffer->offset + this->active_command_index;
|
||||
unsigned len = this->active_next_index - this->active_command_index;
|
||||
this->prepare_draw();
|
||||
|
||||
// Length in number of vertices
|
||||
glDrawArrays(mode, start, len);
|
||||
glDrawArrays(mode, this->map_start, this->map_index);
|
||||
|
||||
this->finalize_draw__no_bind();
|
||||
|
||||
get_error();
|
||||
}
|
||||
|
||||
void pre_bind() {
|
||||
this->vao->bind();
|
||||
this->program->bind();
|
||||
}
|
||||
|
||||
void draw_indexed_no_bind(GLenum mode, GLushort *indices, GLsizei count)
|
||||
/// This method doesn't call prepare_draw/finalize_draw itself, it
|
||||
/// must be handled by the caller. This is because this command
|
||||
/// can be called several times on the same buffer (i.e. multiple
|
||||
/// draw calls between the prepare/finalize)
|
||||
void draw_indexed__raw(GLenum mode, GLushort *indices, GLsizei count)
|
||||
{
|
||||
printf("Draw indexed %d/%lu\n", count, this->map_index);
|
||||
|
||||
this->bind();
|
||||
|
||||
if (this->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct Storage<T> *buffer = this->get_active_buffer();
|
||||
|
||||
GLint base = buffer->offset;
|
||||
|
||||
glDrawElementsBaseVertex(mode,
|
||||
count,
|
||||
GL_UNSIGNED_SHORT,
|
||||
indices,
|
||||
base);
|
||||
glDrawElements(mode, count, GL_UNSIGNED_SHORT, indices);
|
||||
|
||||
get_error();
|
||||
}
|
||||
|
||||
size_t remaining_capacity()
|
||||
{
|
||||
return this->capacity - this->active_next_index;
|
||||
return this->capacity - this->map_index;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,7 @@ RetroGl::RetroGl(VideoClock video_clock)
|
||||
{
|
||||
retro_pixel_format f = RETRO_PIXEL_FORMAT_XRGB8888;
|
||||
if ( !environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &f) ) {
|
||||
puts("Can't set pixel format\n");
|
||||
puts("Can't set pixel format");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ RetroGl::RetroGl(VideoClock video_clock)
|
||||
params.imm_vbo_disable = NULL;
|
||||
|
||||
if ( !glsm_ctl(GLSM_CTL_STATE_CONTEXT_INIT, ¶ms) ) {
|
||||
puts("Failed to init hardware context\n");
|
||||
puts("Failed to init hardware context");
|
||||
// TODO: Move this out to a init function to avoid exceptions?
|
||||
throw std::runtime_error("Failed to init GLSM context.");
|
||||
}
|
||||
@ -88,7 +88,7 @@ RetroGl::~RetroGl() {
|
||||
}
|
||||
|
||||
void RetroGl::context_reset() {
|
||||
puts("OpenGL context reset\n");
|
||||
puts("OpenGL context reset");
|
||||
glsm_ctl(GLSM_CTL_STATE_CONTEXT_RESET, NULL);
|
||||
|
||||
if (!glsm_ctl(GLSM_CTL_STATE_SETUP, NULL))
|
||||
@ -127,7 +127,7 @@ GlRenderer* RetroGl::gl_renderer()
|
||||
case GlState_Valid:
|
||||
return this->state_data.r;
|
||||
default:
|
||||
puts("Attempted to get GL state without GL context!\n");
|
||||
puts("Attempted to get GL state without GL context!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ void RetroGl::prepare_render()
|
||||
renderer = this->state_data.r;
|
||||
break;
|
||||
case GlState_Invalid:
|
||||
puts("Attempted to render a frame without GL context\n");
|
||||
puts("Attempted to render a frame without GL context");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ void RetroGl::finalize_frame()
|
||||
renderer = this->state_data.r;
|
||||
break;
|
||||
case GlState_Invalid:
|
||||
puts("Attempted to render a frame without GL context\n");
|
||||
puts("Attempted to render a frame without GL context");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -229,8 +229,8 @@ void RetroGl::refresh_variables()
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
puts("Couldn't change frontend resolution\n");
|
||||
puts("Try resetting to enable the new configuration\n");
|
||||
puts("Couldn't change frontend resolution");
|
||||
puts("Try resetting to enable the new configuration");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
const GLvoid* gl_offset();
|
||||
};
|
||||
|
||||
/*
|
||||
/*
|
||||
<simias> in order to create the vertex attrib array I need to know:
|
||||
the GL type of the field, the number of components (unary, pair or triple)
|
||||
and the offset within the struct
|
||||
|
Loading…
Reference in New Issue
Block a user