void COGLExtRender::DisBindTexture(GLuint texture, int unitno) { if( m_bEnableMultiTexture ) { pglActiveTexture(GL_TEXTURE0+unitno); OPENGL_CHECK_ERRORS; glBindTexture(GL_TEXTURE_2D, 0); //Not to bind any texture OPENGL_CHECK_ERRORS; } else OGLRender::DisBindTexture(texture, unitno); }
void COGLExtRender::EnableTexUnit(int unitno, BOOL flag) { if( m_texUnitEnabled[unitno] != flag ) { m_texUnitEnabled[unitno] = flag; pglActiveTexture(GL_TEXTURE0_ARB+unitno); OPENGL_CHECK_ERRORS; if( flag == TRUE ) glEnable(GL_TEXTURE_2D); else glDisable(GL_TEXTURE_2D); OPENGL_CHECK_ERRORS; } }
void COGLExtRender::SetTexWrapS(int unitno,GLuint flag) { static GLuint mflag[8]; static GLuint mtex[8]; if( m_curBoundTex[unitno] != mtex[unitno] || mflag[unitno] != flag ) { pglActiveTexture(GL_TEXTURE0+unitno); OPENGL_CHECK_ERRORS; mtex[unitno] = m_curBoundTex[0]; mflag[unitno] = flag; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, flag); OPENGL_CHECK_ERRORS; } }
//======================================================================== void COGLColorCombiner4::InitCombinerCycleFill(void) { for( int i=0; i<m_supportedStages; i++ ) { pglActiveTexture(GL_TEXTURE0_ARB+i); OPENGL_CHECK_ERRORS; m_pOGLRender->EnableTexUnit(i, false); } //pglActiveTexture(GL_TEXTURE0_ARB); //m_pOGLRender->EnableTexUnit(0, false); //pglActiveTexture(GL_TEXTURE1_ARB); //m_pOGLRender->EnableTexUnit(1, false); }
void COGLExtRender::SetTextureUFlag(TextureUVFlag dwFlag, uint32 dwTile) { TileUFlags[dwTile] = dwFlag; if( !m_bEnableMultiTexture ) { OGLRender::SetTextureUFlag(dwFlag, dwTile); return; } int tex; if( dwTile == gRSP.curTile ) tex=0; else if( dwTile == ((gRSP.curTile+1)&7) ) tex=1; else { if( dwTile == ((gRSP.curTile+2)&7) ) tex=2; else if( dwTile == ((gRSP.curTile+3)&7) ) tex=3; else { TRACE2("Incorrect tile number for OGL SetTextureUFlag: cur=%d, tile=%d", gRSP.curTile, dwTile); return; } } for( int textureNo=0; textureNo<8; textureNo++) { if( m_textureUnitMap[textureNo] == tex ) { pglActiveTexture(GL_TEXTURE0_ARB+textureNo); OPENGL_CHECK_ERRORS; COGLTexture* pTexture = g_textures[(gRSP.curTile+tex)&7].m_pCOGLTexture; if( pTexture ) { EnableTexUnit(textureNo,TRUE); BindTexture(pTexture->m_dwTextureName, textureNo); } SetTexWrapS(textureNo, OGLXUVFlagMaps[dwFlag].realFlag); } } }
void COGLExtRender::BindTexture(GLuint texture, int unitno) { if( m_bEnableMultiTexture ) { if( unitno < m_maxTexUnits ) { if( m_curBoundTex[unitno] != texture ) { pglActiveTexture(GL_TEXTURE0_ARB+unitno); OPENGL_CHECK_ERRORS; glBindTexture(GL_TEXTURE_2D,texture); OPENGL_CHECK_ERRORS; m_curBoundTex[unitno] = texture; } } } else { OGLRender::BindTexture(texture, unitno); } }
void COGLColorCombiner4::GenerateCombinerSettingConstants(int index) { OGLExtCombinerSaveType &res = m_vCompiledSettings[index]; float *fv; float tempf[4]; bool isUsed = true; if( res.primIsUsed ) { fv = GetPrimitiveColorfv(); // CONSTANT COLOR } else if( res.envIsUsed ) { fv = GetEnvColorfv(); // CONSTANT COLOR } else if( res.lodFracIsUsed ) { float frac = gRDP.LODFrac / 255.0f; tempf[0] = tempf[1] = tempf[2] = tempf[3] = frac; fv = &tempf[0]; } else { isUsed = false; } if( isUsed ) { for( int i=0; i<res.numOfUnits; i++ ) { pglActiveTexture(GL_TEXTURE0_ARB+i); OPENGL_CHECK_ERRORS; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,fv); OPENGL_CHECK_ERRORS; } } }
static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) { if (gl_teximage_cnt >= MAX_TEXTURES) { RARCH_WARN("Too many texture images. Ignoring ...\n"); return true; } bool linear = true; char filename[PATH_MAX]; char filter[64]; char id[64]; xml_get_prop(filename, sizeof(filename), ptr, "file"); xml_get_prop(filter, sizeof(filter), ptr, "filter"); xml_get_prop(id, sizeof(id), ptr, "id"); struct texture_image img; if (!*id) { RARCH_ERR("Could not find ID in texture.\n"); return false; } if (!*filename) { RARCH_ERR("Could not find filename in texture.\n"); return false; } if (strcmp(filter, "nearest") == 0) linear = false; char tex_path[PATH_MAX]; fill_pathname_resolve_relative(tex_path, shader_path, (const char*)filename, sizeof(tex_path)); RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path); if (!texture_image_load(tex_path, &img)) { RARCH_ERR("Failed to load texture image from: \"%s\"\n", tex_path); return false; } strlcpy(gl_teximage_uniforms[gl_teximage_cnt], (const char*)id, sizeof(gl_teximage_uniforms[0])); glGenTextures(1, &gl_teximage[gl_teximage_cnt]); pglActiveTexture(GL_TEXTURE0 + gl_teximage_cnt + 1); glBindTexture(GL_TEXTURE_2D, gl_teximage[gl_teximage_cnt]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_INTERNAL_FORMAT32, img.width, img.height, 0, driver.gfx_use_rgba ? GL_RGBA : RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, img.pixels); pglActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); free(img.pixels); gl_teximage_cnt++; return true; }
void gl_glsl_set_params(unsigned width, unsigned height, unsigned tex_width, unsigned tex_height, unsigned out_width, unsigned out_height, unsigned frame_count, const struct gl_tex_info *info, const struct gl_tex_info *prev_info, const struct gl_tex_info *fbo_info, unsigned fbo_info_cnt) { // We enforce a certain layout for our various texture types in the texunits. // - Regular frame (rubyTexture) (always bound). // - LUT textures (always bound). // - Original texture (always bound if meaningful). // - FBO textures (always bound if available). // - Previous textures. if (!glsl_enable || (gl_program[active_index] == 0)) return; const struct shader_uniforms *uni = &gl_uniforms[active_index]; float input_size[2] = {(float)width, (float)height}; float output_size[2] = {(float)out_width, (float)out_height}; float texture_size[2] = {(float)tex_width, (float)tex_height}; if (uni->input_size >= 0) pglUniform2fv(uni->input_size, 1, input_size); if (uni->output_size >= 0) pglUniform2fv(uni->output_size, 1, output_size); if (uni->texture_size >= 0) pglUniform2fv(uni->texture_size, 1, texture_size); if (uni->frame_count >= 0) pglUniform1i(uni->frame_count, frame_count); if (uni->frame_direction >= 0) pglUniform1i(uni->frame_direction, g_extern.frame_is_reverse ? -1 : 1); for (unsigned i = 0; i < gl_teximage_cnt; i++) { if (uni->lut_texture[i] >= 0) pglUniform1i(uni->lut_texture[i], i + 1); } unsigned texunit = gl_teximage_cnt + 1; // Set original texture unless we're in first pass (pointless). if (active_index > 1) { if (uni->orig.texture >= 0) { // Bind original texture. pglActiveTexture(GL_TEXTURE0 + texunit); pglUniform1i(uni->orig.texture, texunit); glBindTexture(GL_TEXTURE_2D, info->tex); } texunit++; if (uni->orig.texture_size >= 0) pglUniform2fv(uni->orig.texture_size, 1, info->tex_size); if (uni->orig.input_size >= 0) pglUniform2fv(uni->orig.input_size, 1, info->input_size); // Pass texture coordinates. if (uni->orig.tex_coord >= 0) { int loc = uni->orig.tex_coord; pglEnableVertexAttribArray(loc); pglVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, info->coord); gl_attribs[gl_attrib_index++] = loc; } // Bind new texture in the chain. if (fbo_info_cnt > 0) { pglActiveTexture(GL_TEXTURE0 + texunit + fbo_info_cnt - 1); glBindTexture(GL_TEXTURE_2D, fbo_info[fbo_info_cnt - 1].tex); } // Bind FBO textures. for (unsigned i = 0; i < fbo_info_cnt; i++) { if (uni->pass[i].texture) pglUniform1i(uni->pass[i].texture, texunit); texunit++; if (uni->pass[i].texture_size >= 0) pglUniform2fv(uni->pass[i].texture_size, 1, fbo_info[i].tex_size); if (uni->pass[i].input_size >= 0) pglUniform2fv(uni->pass[i].input_size, 1, fbo_info[i].input_size); if (uni->pass[i].tex_coord >= 0) { int loc = uni->pass[i].tex_coord; pglEnableVertexAttribArray(loc); pglVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, fbo_info[i].coord); gl_attribs[gl_attrib_index++] = loc; } } } else { // First pass, so unbind everything to avoid collitions. // Unbind ORIG. pglActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, 0); GLuint base_tex = texunit + 1; // Unbind any lurking FBO passes. // Rendering to a texture that is bound to a texture unit // sounds very shaky ... ;) for (unsigned i = 0; i < gl_num_programs; i++) { pglActiveTexture(GL_TEXTURE0 + base_tex + i); glBindTexture(GL_TEXTURE_2D, 0); } } // Set previous textures. Only bind if they're actually used. for (unsigned i = 0; i < PREV_TEXTURES; i++) { if (uni->prev[i].texture >= 0) { pglActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, prev_info[i].tex); pglUniform1i(uni->prev[i].texture, texunit++); } texunit++; if (uni->prev[i].texture_size >= 0) pglUniform2fv(uni->prev[i].texture_size, 1, prev_info[i].tex_size); if (uni->prev[i].input_size >= 0) pglUniform2fv(uni->prev[i].input_size, 1, prev_info[i].input_size); // Pass texture coordinates. if (uni->prev[i].tex_coord >= 0) { int loc = uni->prev[i].tex_coord; pglEnableVertexAttribArray(loc); pglVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, prev_info[i].coord); gl_attribs[gl_attrib_index++] = loc; } } pglActiveTexture(GL_TEXTURE0); if (gl_state_tracker) { static struct state_tracker_uniform info[MAX_VARIABLES]; static unsigned cnt = 0; if (active_index == 1) cnt = state_get_uniform(gl_state_tracker, info, MAX_VARIABLES, frame_count); for (unsigned i = 0; i < cnt; i++) { int location = pglGetUniformLocation(gl_program[active_index], info[i].id); pglUniform1f(location, info[i].value); } } }
static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) { if (gl_teximage_cnt >= MAX_TEXTURES) { RARCH_WARN("Too many texture images. Ignoring ...\n"); return true; } bool linear = true; xmlChar *filename = xmlGetProp(ptr, (const xmlChar*)"file"); xmlChar *filter = xmlGetProp(ptr, (const xmlChar*)"filter"); xmlChar *id = xmlGetProp(ptr, (const xmlChar*)"id"); char *last = NULL; struct texture_image img; if (!id) { RARCH_ERR("Could not find ID in texture.\n"); goto error; } if (!filename) { RARCH_ERR("Could not find filename in texture.\n"); goto error; } if (filter && strcmp((const char*)filter, "nearest") == 0) linear = false; char tex_path[PATH_MAX]; strlcpy(tex_path, shader_path, sizeof(tex_path)); last = strrchr(tex_path, '/'); if (!last) last = strrchr(tex_path, '\\'); if (last) last[1] = '\0'; strlcat(tex_path, (const char*)filename, sizeof(tex_path)); RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path); if (!texture_image_load(tex_path, &img)) { RARCH_ERR("Failed to load texture image from: \"%s\"\n", tex_path); goto error; } strlcpy(gl_teximage_uniforms[gl_teximage_cnt], (const char*)id, sizeof(gl_teximage_uniforms[0])); glGenTextures(1, &gl_teximage[gl_teximage_cnt]); pglActiveTexture(GL_TEXTURE0 + gl_teximage_cnt + 1); glBindTexture(GL_TEXTURE_2D, gl_teximage[gl_teximage_cnt]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(GL_TEXTURE_2D, 0, RARCH_GL_INTERNAL_FORMAT32, img.width, img.height, 0, RARCH_GL_TEXTURE_TYPE32, RARCH_GL_FORMAT32, img.pixels); pglActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); free(img.pixels); xmlFree(filename); xmlFree(id); if (filter) xmlFree(filter); gl_teximage_cnt++; return true; error: if (filename) xmlFree(filename); if (filter) xmlFree(filter); if (filter) xmlFree(id); return false; }
void gl_glsl_set_params(unsigned width, unsigned height, unsigned tex_width, unsigned tex_height, unsigned out_width, unsigned out_height, unsigned frame_count, const struct gl_tex_info *info, const struct gl_tex_info *prev_info, const struct gl_tex_info *fbo_info, unsigned fbo_info_cnt) { // We enforce a certain layout for our various texture types in the texunits. // - Regular SNES frame (rubyTexture) (always bound). // - LUT textures (always bound). // - Original texture (always bound if meaningful). // - FBO textures (always bound if available). // - Previous textures. if (!glsl_enable || (gl_program[active_index] == 0)) return; GLint location; float inputSize[2] = {(float)width, (float)height}; location = pglGetUniformLocation(gl_program[active_index], "rubyInputSize"); pglUniform2fv(location, 1, inputSize); float outputSize[2] = {(float)out_width, (float)out_height}; location = pglGetUniformLocation(gl_program[active_index], "rubyOutputSize"); pglUniform2fv(location, 1, outputSize); float textureSize[2] = {(float)tex_width, (float)tex_height}; location = pglGetUniformLocation(gl_program[active_index], "rubyTextureSize"); pglUniform2fv(location, 1, textureSize); location = pglGetUniformLocation(gl_program[active_index], "rubyFrameCount"); pglUniform1i(location, frame_count); location = pglGetUniformLocation(gl_program[active_index], "rubyFrameDirection"); pglUniform1i(location, g_extern.frame_is_reverse ? -1 : 1); for (unsigned i = 0; i < gl_teximage_cnt; i++) { location = pglGetUniformLocation(gl_program[active_index], gl_teximage_uniforms[i]); pglUniform1i(location, i + 1); } unsigned texunit = gl_teximage_cnt + 1; // Set original texture unless we're in first pass (pointless). if (active_index > 1) { // Bind original texture. pglActiveTexture(GL_TEXTURE0 + texunit); location = pglGetUniformLocation(gl_program[active_index], "rubyOrigTexture"); pglUniform1i(location, texunit++); glBindTexture(GL_TEXTURE_2D, info->tex); location = pglGetUniformLocation(gl_program[active_index], "rubyOrigTextureSize"); pglUniform2fv(location, 1, info->tex_size); location = pglGetUniformLocation(gl_program[active_index], "rubyOrigInputSize"); pglUniform2fv(location, 1, info->input_size); // Pass texture coordinates. location = pglGetAttribLocation(gl_program[active_index], "rubyOrigTexCoord"); if (location >= 0) { pglEnableVertexAttribArray(location); pglVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 0, info->coord); gl_attribs[gl_attrib_index++] = location; } // Bind new texture in the chain. if (fbo_info_cnt > 0) { pglActiveTexture(GL_TEXTURE0 + texunit + fbo_info_cnt - 1); glBindTexture(GL_TEXTURE_2D, fbo_info[fbo_info_cnt - 1].tex); } // Bind FBO textures. for (unsigned i = 0; i < fbo_info_cnt; i++) { char attrib_buf[64]; snprintf(attrib_buf, sizeof(attrib_buf), "rubyPass%uTexture", i + 1); location = pglGetUniformLocation(gl_program[active_index], attrib_buf); pglUniform1i(location, texunit++); snprintf(attrib_buf, sizeof(attrib_buf), "rubyPass%uTextureSize", i + 1); location = pglGetUniformLocation(gl_program[active_index], attrib_buf); pglUniform2fv(location, 1, fbo_info[i].tex_size); snprintf(attrib_buf, sizeof(attrib_buf), "rubyPass%uInputSize", i + 1); location = pglGetUniformLocation(gl_program[active_index], attrib_buf); pglUniform2fv(location, 1, fbo_info[i].input_size); snprintf(attrib_buf, sizeof(attrib_buf), "rubyPass%uTexCoord", i + 1); location = pglGetAttribLocation(gl_program[active_index], attrib_buf); if (location >= 0) { pglEnableVertexAttribArray(location); pglVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 0, fbo_info[i].coord); gl_attribs[gl_attrib_index++] = location; } } } else { // First pass, so unbind everything to avoid collitions. // Unbind ORIG. pglActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, 0); GLuint base_tex = texunit + 1; // Unbind any lurking FBO passes. // Rendering to a texture that is bound to a texture unit // sounds very shaky ... ;) for (unsigned i = 0; i < gl_num_programs; i++) { pglActiveTexture(GL_TEXTURE0 + base_tex + i); glBindTexture(GL_TEXTURE_2D, 0); } } // Set previous textures. Only bind if they're actually used. for (unsigned i = 0; i < PREV_TEXTURES; i++) { char attr_buf_tex[64]; char attr_buf_tex_size[64]; char attr_buf_input_size[64]; char attr_buf_coord[64]; static const char *prev_names[PREV_TEXTURES] = { "Prev", "Prev1", "Prev2", "Prev3", "Prev4", "Prev5", "Prev6", }; snprintf(attr_buf_tex, sizeof(attr_buf_tex), "ruby%sTexture", prev_names[i]); snprintf(attr_buf_tex_size, sizeof(attr_buf_tex_size), "ruby%sTextureSize", prev_names[i]); snprintf(attr_buf_input_size, sizeof(attr_buf_input_size), "ruby%sInputSize", prev_names[i]); snprintf(attr_buf_coord, sizeof(attr_buf_coord), "ruby%sTexCoord", prev_names[i]); location = pglGetUniformLocation(gl_program[active_index], attr_buf_tex); if (location >= 0) { pglActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, prev_info[i].tex); pglUniform1i(location, texunit++); } location = pglGetUniformLocation(gl_program[active_index], attr_buf_tex_size); pglUniform2fv(location, 1, prev_info[i].tex_size); location = pglGetUniformLocation(gl_program[active_index], attr_buf_input_size); pglUniform2fv(location, 1, prev_info[i].input_size); // Pass texture coordinates. location = pglGetAttribLocation(gl_program[active_index], attr_buf_coord); if (location >= 0) { pglEnableVertexAttribArray(location); pglVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 0, prev_info[i].coord); gl_attribs[gl_attrib_index++] = location; } } pglActiveTexture(GL_TEXTURE0); if (gl_state_tracker) { static struct state_tracker_uniform info[MAX_VARIABLES]; static unsigned cnt = 0; if (active_index == 1) cnt = state_get_uniform(gl_state_tracker, info, MAX_VARIABLES, frame_count); for (unsigned i = 0; i < cnt; i++) { location = pglGetUniformLocation(gl_program[active_index], info[i].id); pglUniform1f(location, info[i].value); } } }
void COGLExtRender::ApplyTextureFilter() { static uint32 minflag[8], magflag[8]; static uint32 mtex[8]; int iMinFilter, iMagFilter; for( int i=0; i<m_maxTexUnits; i++ ) { //Compute iMinFilter and iMagFilter if(m_dwMinFilter == FILTER_LINEAR) //Texture will use filtering { iMagFilter = GL_LINEAR; //Texture filtering method user want switch(options.mipmapping) { case TEXTURE_BILINEAR_FILTER: iMinFilter = GL_LINEAR_MIPMAP_NEAREST; break; case TEXTURE_TRILINEAR_FILTER: iMinFilter = GL_LINEAR_MIPMAP_LINEAR; break; case TEXTURE_NO_FILTER: iMinFilter = GL_NEAREST_MIPMAP_NEAREST; break; case TEXTURE_NO_MIPMAP: default: //Bilinear without mipmap iMinFilter = GL_LINEAR; } } else //dont use filtering, all is nearest { iMagFilter = GL_NEAREST; if(options.mipmapping) { iMinFilter = GL_NEAREST_MIPMAP_NEAREST; } else { iMinFilter = GL_NEAREST; } } if( m_texUnitEnabled[i] ) { if( mtex[i] != m_curBoundTex[i] ) { mtex[i] = m_curBoundTex[i]; pglActiveTexture(GL_TEXTURE0_ARB+i); OPENGL_CHECK_ERRORS; minflag[i] = m_dwMinFilter; magflag[i] = m_dwMagFilter; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iMinFilter); OPENGL_CHECK_ERRORS; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iMagFilter); OPENGL_CHECK_ERRORS; } else { if( minflag[i] != (unsigned int)m_dwMinFilter ) { minflag[i] = m_dwMinFilter; pglActiveTexture(GL_TEXTURE0_ARB+i); OPENGL_CHECK_ERRORS; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iMinFilter); OPENGL_CHECK_ERRORS; } if( magflag[i] != (unsigned int)m_dwMagFilter ) { magflag[i] = m_dwMagFilter; pglActiveTexture(GL_TEXTURE0_ARB+i); OPENGL_CHECK_ERRORS; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iMagFilter); OPENGL_CHECK_ERRORS; } } } } }
static void gl_glsl_set_params(unsigned width, unsigned height, unsigned tex_width, unsigned tex_height, unsigned out_width, unsigned out_height, unsigned frame_count, const struct gl_tex_info *info, const struct gl_tex_info *prev_info, const struct gl_tex_info *fbo_info, unsigned fbo_info_cnt) { // We enforce a certain layout for our various texture types in the texunits. // - Regular frame (Texture) (always bound). // - LUT textures (always bound). // - Original texture (always bound if meaningful). // - FBO textures (always bound if available). // - Previous textures. if (!glsl_enable || (gl_program[active_index] == 0)) return; GLfloat buffer[128]; size_t size = 0; struct glsl_attrib attribs[32]; size_t attribs_size = 0; struct glsl_attrib *attr = attribs; const struct shader_uniforms *uni = &gl_uniforms[active_index]; float input_size[2] = {(float)width, (float)height}; float output_size[2] = {(float)out_width, (float)out_height}; float texture_size[2] = {(float)tex_width, (float)tex_height}; if (uni->input_size >= 0) pglUniform2fv(uni->input_size, 1, input_size); if (uni->output_size >= 0) pglUniform2fv(uni->output_size, 1, output_size); if (uni->texture_size >= 0) pglUniform2fv(uni->texture_size, 1, texture_size); if (uni->frame_count >= 0 && active_index) { unsigned modulo = glsl_shader->pass[active_index - 1].frame_count_mod; if (modulo) frame_count %= modulo; pglUniform1i(uni->frame_count, frame_count); } if (uni->frame_direction >= 0) pglUniform1i(uni->frame_direction, g_extern.frame_is_reverse ? -1 : 1); for (unsigned i = 0; i < glsl_shader->luts; i++) { if (uni->lut_texture[i] >= 0) { // Have to rebind as HW render could override this. pglActiveTexture(GL_TEXTURE0 + i + 1); glBindTexture(GL_TEXTURE_2D, gl_teximage[i]); pglUniform1i(uni->lut_texture[i], i + 1); } } unsigned texunit = glsl_shader->luts + 1; // Set original texture unless we're in first pass (pointless). if (active_index > 1) { if (uni->orig.texture >= 0) { // Bind original texture. pglActiveTexture(GL_TEXTURE0 + texunit); pglUniform1i(uni->orig.texture, texunit); glBindTexture(GL_TEXTURE_2D, info->tex); } texunit++; if (uni->orig.texture_size >= 0) pglUniform2fv(uni->orig.texture_size, 1, info->tex_size); if (uni->orig.input_size >= 0) pglUniform2fv(uni->orig.input_size, 1, info->input_size); // Pass texture coordinates. if (uni->orig.tex_coord >= 0) { attr->loc = uni->orig.tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, info->coord, 8 * sizeof(GLfloat)); size += 8; } // Bind new texture in the chain. if (fbo_info_cnt > 0) { pglActiveTexture(GL_TEXTURE0 + texunit + fbo_info_cnt - 1); glBindTexture(GL_TEXTURE_2D, fbo_info[fbo_info_cnt - 1].tex); } // Bind FBO textures. for (unsigned i = 0; i < fbo_info_cnt; i++) { if (uni->pass[i].texture) pglUniform1i(uni->pass[i].texture, texunit); texunit++; if (uni->pass[i].texture_size >= 0) pglUniform2fv(uni->pass[i].texture_size, 1, fbo_info[i].tex_size); if (uni->pass[i].input_size >= 0) pglUniform2fv(uni->pass[i].input_size, 1, fbo_info[i].input_size); if (uni->pass[i].tex_coord >= 0) { attr->loc = uni->pass[i].tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, fbo_info[i].coord, 8 * sizeof(GLfloat)); size += 8; } } } else { // First pass, so unbind everything to avoid collitions. // Unbind ORIG. pglActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, 0); GLuint base_tex = texunit + 1; // Unbind any lurking FBO passes. // Rendering to a texture that is bound to a texture unit // sounds very shaky ... ;) for (unsigned i = 0; i < glsl_shader->passes; i++) { pglActiveTexture(GL_TEXTURE0 + base_tex + i); glBindTexture(GL_TEXTURE_2D, 0); } } // Set previous textures. Only bind if they're actually used. for (unsigned i = 0; i < PREV_TEXTURES; i++) { if (uni->prev[i].texture >= 0) { pglActiveTexture(GL_TEXTURE0 + texunit); glBindTexture(GL_TEXTURE_2D, prev_info[i].tex); pglUniform1i(uni->prev[i].texture, texunit++); } texunit++; if (uni->prev[i].texture_size >= 0) pglUniform2fv(uni->prev[i].texture_size, 1, prev_info[i].tex_size); if (uni->prev[i].input_size >= 0) pglUniform2fv(uni->prev[i].input_size, 1, prev_info[i].input_size); // Pass texture coordinates. if (uni->prev[i].tex_coord >= 0) { attr->loc = uni->prev[i].tex_coord; attr->size = 2; attr->offset = size * sizeof(GLfloat); attribs_size++; attr++; memcpy(buffer + size, prev_info[i].coord, 8 * sizeof(GLfloat)); size += 8; } } if (size) { gl_glsl_set_attribs(glsl_vbo[active_index].vbo_secondary, glsl_vbo[active_index].buffer_secondary, &glsl_vbo[active_index].size_secondary, buffer, size, attribs, attribs_size); } pglActiveTexture(GL_TEXTURE0); if (gl_state_tracker) { static struct state_tracker_uniform info[GFX_MAX_VARIABLES]; static unsigned cnt = 0; if (active_index == 1) cnt = state_get_uniform(gl_state_tracker, info, GFX_MAX_VARIABLES, frame_count); for (unsigned i = 0; i < cnt; i++) { int location = pglGetUniformLocation(gl_program[active_index], info[i].id); pglUniform1f(location, info[i].value); } } }