Merge pull request #1462 from admshao/gl-fbo-rework
libobs-opengl: Store FBOs per texture instead of per devicemaster
commit
f96a24b746
|
@ -57,13 +57,11 @@ bool gl_init_face(GLenum target, GLenum type, uint32_t num_levels,
|
|||
return success;
|
||||
}
|
||||
|
||||
static bool gl_copy_fbo(struct gs_device *device,
|
||||
GLuint dst, GLenum dst_target, uint32_t dst_x, uint32_t dst_y,
|
||||
GLuint src, GLenum src_target, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_color_format format)
|
||||
static bool gl_copy_fbo(struct gs_texture *dst, uint32_t dst_x, uint32_t dst_y,
|
||||
struct gs_texture *src, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t width, uint32_t height)
|
||||
{
|
||||
struct fbo_info *fbo = get_fbo(device, width, height, format);
|
||||
struct fbo_info *fbo = get_fbo(src, width, height);
|
||||
GLint last_fbo;
|
||||
bool success = false;
|
||||
|
||||
|
@ -74,11 +72,11 @@ static bool gl_copy_fbo(struct gs_device *device,
|
|||
return false;
|
||||
if (!gl_bind_framebuffer(GL_READ_FRAMEBUFFER, fbo->fbo))
|
||||
return false;
|
||||
if (!gl_bind_texture(dst_target, dst))
|
||||
if (!gl_bind_texture(dst->gl_target, dst->texture))
|
||||
goto fail;
|
||||
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0,
|
||||
src_target, src, 0);
|
||||
src->gl_target, src->texture, 0);
|
||||
if (!gl_success("glFrameBufferTexture2D"))
|
||||
goto fail;
|
||||
|
||||
|
@ -86,7 +84,7 @@ static bool gl_copy_fbo(struct gs_device *device,
|
|||
if (!gl_success("glReadBuffer"))
|
||||
goto fail;
|
||||
|
||||
glCopyTexSubImage2D(dst_target, 0, dst_x, dst_y, src_x, src_y,
|
||||
glCopyTexSubImage2D(dst->gl_target, 0, dst_x, dst_y, src_x, src_y,
|
||||
width, height);
|
||||
if (!gl_success("glCopyTexSubImage2D"))
|
||||
goto fail;
|
||||
|
@ -94,7 +92,7 @@ static bool gl_copy_fbo(struct gs_device *device,
|
|||
success = true;
|
||||
|
||||
fail:
|
||||
if (!gl_bind_texture(dst_target, 0))
|
||||
if (!gl_bind_texture(dst->gl_target, 0))
|
||||
success = false;
|
||||
if (!gl_bind_framebuffer(GL_READ_FRAMEBUFFER, last_fbo))
|
||||
success = false;
|
||||
|
@ -102,29 +100,28 @@ fail:
|
|||
return success;
|
||||
}
|
||||
|
||||
bool gl_copy_texture(struct gs_device *device,
|
||||
GLuint dst, GLenum dst_target, uint32_t dst_x, uint32_t dst_y,
|
||||
GLuint src, GLenum src_target, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t width, uint32_t height, enum gs_color_format format)
|
||||
bool gl_copy_texture(struct gs_device *device, struct gs_texture *dst,
|
||||
uint32_t dst_x, uint32_t dst_y, struct gs_texture *src,
|
||||
uint32_t src_x, uint32_t src_y, uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (device->copy_type == COPY_TYPE_ARB) {
|
||||
glCopyImageSubData(src, src_target, 0, src_x, src_y, 0,
|
||||
dst, dst_target, 0, dst_x, dst_y, 0,
|
||||
width, height, 1);
|
||||
glCopyImageSubData(src->texture, src->gl_target, 0, src_x,
|
||||
src_y, 0, dst->texture, dst->gl_target, 0,
|
||||
dst_x, dst_y, 0, width, height, 1);
|
||||
success = gl_success("glCopyImageSubData");
|
||||
|
||||
} else if (device->copy_type == COPY_TYPE_NV) {
|
||||
glCopyImageSubDataNV(src, src_target, 0, src_x, src_y, 0,
|
||||
dst, dst_target, 0, dst_x, dst_y, 0,
|
||||
width, height, 1);
|
||||
glCopyImageSubDataNV(src->texture, src->gl_target, 0, src_x,
|
||||
src_y, 0, dst->texture, dst->gl_target, 0,
|
||||
dst_x, dst_y, 0, width, height, 1);
|
||||
success = gl_success("glCopyImageSubDataNV");
|
||||
|
||||
} else if (device->copy_type == COPY_TYPE_FBO_BLIT) {
|
||||
success = gl_copy_fbo(device, dst, dst_target, dst_x, dst_y,
|
||||
src, src_target, src_x, src_y,
|
||||
width, height, format);
|
||||
success = gl_copy_fbo(dst, dst_x, dst_y, src, src_x, src_y,
|
||||
width, height);
|
||||
if (!success)
|
||||
blog(LOG_ERROR, "gl_copy_texture failed");
|
||||
}
|
||||
|
|
|
@ -148,11 +148,10 @@ extern bool gl_init_face(GLenum target, GLenum type, uint32_t num_levels,
|
|||
uint32_t width, uint32_t height, uint32_t size,
|
||||
const uint8_t ***p_data);
|
||||
|
||||
extern bool gl_copy_texture(struct gs_device *device,
|
||||
GLuint dst, GLenum dst_target, uint32_t dst_x, uint32_t dst_y,
|
||||
GLuint src, GLenum src_target, uint32_t src_x, uint32_t src_y,
|
||||
uint32_t width, uint32_t height,
|
||||
enum gs_color_format format);
|
||||
extern bool gl_copy_texture(struct gs_device *device, struct gs_texture *dst,
|
||||
uint32_t dst_x, uint32_t dst_y, struct gs_texture *src,
|
||||
uint32_t src_x, uint32_t src_y, uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
extern bool gl_create_buffer(GLenum target, GLuint *buffer, GLsizeiptr size,
|
||||
const GLvoid *data, GLenum usage);
|
||||
|
|
|
@ -124,7 +124,7 @@ void device_stage_texture(gs_device_t *device, gs_stagesurf_t *dst,
|
|||
if (!gl_bind_buffer(GL_PIXEL_PACK_BUFFER, dst->pack_buffer))
|
||||
goto failed;
|
||||
|
||||
fbo = get_fbo(device, dst->width, dst->height, dst->format);
|
||||
fbo = get_fbo(src, dst->width, dst->height);
|
||||
|
||||
if (!gl_get_integer_v(GL_READ_FRAMEBUFFER_BINDING, &last_fbo))
|
||||
goto failed_unbind_buffer;
|
||||
|
@ -152,6 +152,8 @@ failed_unbind_buffer:
|
|||
failed:
|
||||
if (!success)
|
||||
blog(LOG_ERROR, "device_stage_texture (GL) failed");
|
||||
|
||||
UNUSED_PARAMETER(device);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
@ -259,16 +259,10 @@ fail:
|
|||
void device_destroy(gs_device_t *device)
|
||||
{
|
||||
if (device) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < device->fbos.num; i++)
|
||||
fbo_info_destroy(device->fbos.array[i]);
|
||||
|
||||
while (device->first_program)
|
||||
gs_program_destroy(device->first_program);
|
||||
|
||||
da_free(device->proj_stack);
|
||||
da_free(device->fbos);
|
||||
gl_platform_destroy(device->plat);
|
||||
bfree(device);
|
||||
}
|
||||
|
@ -658,46 +652,37 @@ static bool get_tex_dimensions(gs_texture_t *tex, uint32_t *width,
|
|||
* This automatically manages FBOs so that render targets are always given
|
||||
* an FBO that matches their width/height/format to maximize optimization
|
||||
*/
|
||||
struct fbo_info *get_fbo(struct gs_device *device,
|
||||
uint32_t width, uint32_t height, enum gs_color_format format)
|
||||
struct fbo_info *get_fbo(gs_texture_t *tex, uint32_t width, uint32_t height)
|
||||
{
|
||||
size_t i;
|
||||
if (tex->fbo && tex->fbo->width == width &&
|
||||
tex->fbo->height == height &&
|
||||
tex->fbo->format == tex->format)
|
||||
return tex->fbo;
|
||||
|
||||
GLuint fbo;
|
||||
struct fbo_info *ptr;
|
||||
|
||||
for (i = 0; i < device->fbos.num; i++) {
|
||||
ptr = device->fbos.array[i];
|
||||
|
||||
if (ptr->width == width && ptr->height == height &&
|
||||
ptr->format == format)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
if (!gl_success("glGenFramebuffers"))
|
||||
return NULL;
|
||||
|
||||
ptr = bmalloc(sizeof(struct fbo_info));
|
||||
ptr->fbo = fbo;
|
||||
ptr->width = width;
|
||||
ptr->height = height;
|
||||
ptr->format = format;
|
||||
ptr->cur_render_target = NULL;
|
||||
ptr->cur_render_side = 0;
|
||||
ptr->cur_zstencil_buffer = NULL;
|
||||
tex->fbo = bmalloc(sizeof(struct fbo_info));
|
||||
tex->fbo->fbo = fbo;
|
||||
tex->fbo->width = width;
|
||||
tex->fbo->height = height;
|
||||
tex->fbo->format = tex->format;
|
||||
tex->fbo->cur_render_target = NULL;
|
||||
tex->fbo->cur_render_side = 0;
|
||||
tex->fbo->cur_zstencil_buffer = NULL;
|
||||
|
||||
da_push_back(device->fbos, &ptr);
|
||||
return ptr;
|
||||
return tex->fbo;
|
||||
}
|
||||
|
||||
static inline struct fbo_info *get_fbo_by_tex(struct gs_device *device,
|
||||
gs_texture_t *tex)
|
||||
static inline struct fbo_info *get_fbo_by_tex(gs_texture_t *tex)
|
||||
{
|
||||
uint32_t width, height;
|
||||
if (!get_tex_dimensions(tex, &width, &height))
|
||||
return NULL;
|
||||
|
||||
return get_fbo(device, width, height, tex->format);
|
||||
return get_fbo(tex, width, height);
|
||||
}
|
||||
|
||||
static bool set_current_fbo(gs_device_t *device, struct fbo_info *fbo)
|
||||
|
@ -783,7 +768,7 @@ static bool set_target(gs_device_t *device, gs_texture_t *tex, int side,
|
|||
if (!tex)
|
||||
return set_current_fbo(device, NULL);
|
||||
|
||||
fbo = get_fbo_by_tex(device, tex);
|
||||
fbo = get_fbo_by_tex(tex);
|
||||
if (!fbo)
|
||||
return false;
|
||||
|
||||
|
@ -885,9 +870,8 @@ void device_copy_texture_region(gs_device_t *device,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!gl_copy_texture(device, dst->texture, dst->gl_target, dst_x, dst_y,
|
||||
src->texture, src->gl_target, src_x, src_y,
|
||||
nw, nh, src->format))
|
||||
if (!gl_copy_texture(device, dst, dst_x, dst_y, src, src_x, src_y, nw,
|
||||
nh))
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
|
|
|
@ -409,6 +409,7 @@ struct gs_texture {
|
|||
bool gen_mipmaps;
|
||||
|
||||
gs_samplerstate_t *cur_sampler;
|
||||
struct fbo_info *fbo;
|
||||
};
|
||||
|
||||
struct gs_texture_2d {
|
||||
|
@ -501,12 +502,11 @@ struct gs_device {
|
|||
|
||||
DARRAY(struct matrix4) proj_stack;
|
||||
|
||||
DARRAY(struct fbo_info*) fbos;
|
||||
struct fbo_info *cur_fbo;
|
||||
};
|
||||
|
||||
extern struct fbo_info *get_fbo(struct gs_device *device,
|
||||
uint32_t width, uint32_t height, enum gs_color_format format);
|
||||
extern struct fbo_info *get_fbo(gs_texture_t *tex, uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
extern void gl_update(gs_device_t *device);
|
||||
|
||||
|
|
|
@ -138,6 +138,9 @@ void gs_texture_destroy(gs_texture_t *tex)
|
|||
if (tex->texture)
|
||||
gl_delete_textures(1, &tex->texture);
|
||||
|
||||
if (tex->fbo)
|
||||
fbo_info_destroy(tex->fbo);
|
||||
|
||||
bfree(tex);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,10 +92,11 @@ void gs_cubetexture_destroy(gs_texture_t *tex)
|
|||
if (!tex)
|
||||
return;
|
||||
|
||||
if (tex->texture) {
|
||||
glDeleteTextures(1, &tex->texture);
|
||||
gl_success("glDeleteTextures");
|
||||
}
|
||||
if (tex->texture)
|
||||
gl_delete_textures(1, &tex->texture);
|
||||
|
||||
if (tex->fbo)
|
||||
fbo_info_destroy(tex->fbo);
|
||||
|
||||
bfree(tex);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue