gl_common.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,599 行 · 第 1/4 页
C
1,599 行
ppm_skip(f); if (fscanf(f, "%u", &h) != 1) return 0; ppm_skip(f); if (fscanf(f, "%u", &m) != 1) return 0; val = fgetc(f); if (!isspace(val)) return 0; if (w > MAXDIM || h > MAXDIM) return 0; bpp = (m > 255) ? 6 : 3; data = malloc(w * h * bpp); if (fread(data, w * bpp, h, f) != h) return 0; if (!fmt) { fmt = (m > 255) ? hqtexfmt : 3; if (fmt == GL_FLOAT_RGB32_NV && target != GL_TEXTURE_RECTANGLE) fmt = GL_RGB16; } glCreateClearTex(target, fmt, filter, w, h, 0); glUploadTex(target, GL_RGB, (m > 255) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE, data, w * bpp, 0, 0, w, h, 0); free(data); if (width) *width = w; if (height) *height = h; if (maxval) *maxval = m; return 1;}/** * \brief return the number of bytes per pixel for the given format * \param format OpenGL format * \param type OpenGL type * \return bytes per pixel * \ingroup glgeneral * * Does not handle all possible variants, just those used by MPlayer */int glFmt2bpp(GLenum format, GLenum type) { int component_size = 0; switch (type) { case GL_UNSIGNED_BYTE_3_3_2: case GL_UNSIGNED_BYTE_2_3_3_REV: return 1; case GL_UNSIGNED_SHORT_5_5_5_1: case GL_UNSIGNED_SHORT_1_5_5_5_REV: case GL_UNSIGNED_SHORT_5_6_5: case GL_UNSIGNED_SHORT_5_6_5_REV: return 2; case GL_UNSIGNED_BYTE: component_size = 1; break; case GL_UNSIGNED_SHORT: component_size = 2; break; } switch (format) { case GL_LUMINANCE: case GL_ALPHA: return component_size; case GL_RGB: case GL_BGR: return 3 * component_size; case GL_RGBA: case GL_BGRA: return 4 * component_size; } return 0; // unknown}/** * \brief upload a texture, handling things like stride and slices * \param target texture target, usually GL_TEXTURE_2D * \param format OpenGL format of data * \param type OpenGL type of data * \param dataptr data to upload * \param stride data stride * \param x x offset in texture * \param y y offset in texture * \param w width of the texture part to upload * \param h height of the texture part to upload * \param slice height of an upload slice, 0 for all at once * \ingroup gltexture */void glUploadTex(GLenum target, GLenum format, GLenum type, const void *dataptr, int stride, int x, int y, int w, int h, int slice) { const uint8_t *data = dataptr; int y_max = y + h; if (w <= 0 || h <= 0) return; if (slice <= 0) slice = h; if (stride < 0) { data += (h - 1) * stride; stride = -stride; } // this is not always correct, but should work for MPlayer glAdjustAlignment(stride); glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); for (; y + slice <= y_max; y += slice) { glTexSubImage2D(target, 0, x, y, w, slice, format, type, data); data += stride * slice; } if (y < y_max) glTexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data);}static void fillUVcoeff(GLfloat *ucoef, GLfloat *vcoef, float uvcos, float uvsin) { int i; ucoef[0] = 0 * uvcos + 1.403 * uvsin; vcoef[0] = 0 * uvsin + 1.403 * uvcos; ucoef[1] = -0.344 * uvcos + -0.714 * uvsin; vcoef[1] = -0.344 * uvsin + -0.714 * uvcos; ucoef[2] = 1.770 * uvcos + 0 * uvsin; vcoef[2] = 1.770 * uvsin + 0 * uvcos; ucoef[3] = 0; vcoef[3] = 0; // Coefficients (probably) must be in [0, 1] range, whereas they originally // are in [-2, 2] range, so here comes the trick: // First put them in the [-0.5, 0.5] range, then add 0.5. // This can be undone with the HALF_BIAS and SCALE_BY_FOUR arguments // for CombinerInput and CombinerOutput (or the respective ATI variants) for (i = 0; i < 4; i++) { ucoef[i] = ucoef[i] * 0.25 + 0.5; vcoef[i] = vcoef[i] * 0.25 + 0.5; }}/** * \brief Setup register combiners for YUV to RGB conversion. * \param uvcos used for saturation and hue adjustment * \param uvsin used for saturation and hue adjustment */static void glSetupYUVCombiners(float uvcos, float uvsin) { GLfloat ucoef[4]; GLfloat vcoef[4]; GLint i; if (!CombinerInput || !CombinerOutput || !CombinerParameterfv || !CombinerParameteri) { mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner functions missing!\n"); return; } glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &i); if (i < 2) mp_msg(MSGT_VO, MSGL_ERR, "[gl] 2 general combiners needed for YUV combiner support (found %i)\n", i); glGetIntegerv (GL_MAX_TEXTURE_UNITS, &i); if (i < 3) mp_msg(MSGT_VO, MSGL_ERR, "[gl] 3 texture units needed for YUV combiner support (found %i)\n", i); fillUVcoeff(ucoef, vcoef, uvcos, uvsin); CombinerParameterfv(GL_CONSTANT_COLOR0_NV, ucoef); CombinerParameterfv(GL_CONSTANT_COLOR1_NV, vcoef); // UV first, like this green component cannot overflow CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE1, GL_HALF_BIAS_NORMAL_NV, GL_RGB); CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_CONSTANT_COLOR0_NV, GL_HALF_BIAS_NORMAL_NV, GL_RGB); CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE2, GL_HALF_BIAS_NORMAL_NV, GL_RGB); CombinerInput(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_CONSTANT_COLOR1_NV, GL_HALF_BIAS_NORMAL_NV, GL_RGB); CombinerOutput(GL_COMBINER0_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE); // stage 2 CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB); CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB); CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE0, GL_SIGNED_IDENTITY_NV, GL_RGB); CombinerInput(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB); CombinerOutput(GL_COMBINER1_NV, GL_RGB, GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE); // leave final combiner stage in default mode CombinerParameteri(GL_NUM_GENERAL_COMBINERS_NV, 2);}/** * \brief Setup ATI version of register combiners for YUV to RGB conversion. * \param uvcos used for saturation and hue adjustment * \param uvsin used for saturation and hue adjustment * * ATI called this fragment shader, but the name is confusing in the * light of a very different OpenGL 2.0 extension with the same name */static void glSetupYUVCombinersATI(float uvcos, float uvsin) { GLfloat ucoef[4]; GLfloat vcoef[4]; GLint i; if (!BeginFragmentShader || !EndFragmentShader || !SetFragmentShaderConstant || !SampleMap || !ColorFragmentOp2 || !ColorFragmentOp3) { mp_msg(MSGT_VO, MSGL_FATAL, "[gl] Combiner (ATI) functions missing!\n"); return; } glGetIntegerv(GL_NUM_FRAGMENT_REGISTERS_ATI, &i); if (i < 3) mp_msg(MSGT_VO, MSGL_ERR, "[gl] 3 registers needed for YUV combiner (ATI) support (found %i)\n", i); glGetIntegerv (GL_MAX_TEXTURE_UNITS, &i); if (i < 3) mp_msg(MSGT_VO, MSGL_ERR, "[gl] 3 texture units needed for YUV combiner (ATI) support (found %i)\n", i); fillUVcoeff(ucoef, vcoef, uvcos, uvsin); BeginFragmentShader(); SetFragmentShaderConstant(GL_CON_0_ATI, ucoef); SetFragmentShaderConstant(GL_CON_1_ATI, vcoef); SampleMap(GL_REG_0_ATI, GL_TEXTURE0, GL_SWIZZLE_STR_ATI); SampleMap(GL_REG_1_ATI, GL_TEXTURE1, GL_SWIZZLE_STR_ATI); SampleMap(GL_REG_2_ATI, GL_TEXTURE2, GL_SWIZZLE_STR_ATI); // UV first, like this green component cannot overflow ColorFragmentOp2(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, GL_REG_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, GL_CON_0_ATI, GL_NONE, GL_BIAS_BIT_ATI); ColorFragmentOp3(GL_MAD_ATI, GL_REG_2_ATI, GL_NONE, GL_4X_BIT_ATI, GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI, GL_CON_1_ATI, GL_NONE, GL_BIAS_BIT_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE); ColorFragmentOp2(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_REG_2_ATI, GL_NONE, GL_NONE); EndFragmentShader();}/** * \brief helper function for gen_spline_lookup_tex * \param x subpixel-position ((0,1) range) to calculate weights for * \param dst where to store transformed weights, must provide space for 4 GLfloats * * calculates the weights and stores them after appropriate transformation * for the scaler fragment program. */static void store_weights(float x, GLfloat *dst) { float w0 = (((-1 * x + 3) * x - 3) * x + 1) / 6; float w1 = ((( 3 * x - 6) * x + 0) * x + 4) / 6; float w2 = (((-3 * x + 3) * x + 3) * x + 1) / 6; float w3 = ((( 1 * x + 0) * x + 0) * x + 0) / 6; *dst++ = 1 + x - w1 / (w0 + w1); *dst++ = 1 - x + w3 / (w2 + w3); *dst++ = w0 + w1; *dst++ = 0;}//! to avoid artefacts this should be rather large#define LOOKUP_BSPLINE_RES (2 * 1024)/** * \brief creates the 1D lookup texture needed for fast higher-order filtering * \param unit texture unit to attach texture to */static void gen_spline_lookup_tex(GLenum unit) { GLfloat tex[4 * LOOKUP_BSPLINE_RES]; GLfloat *tp = tex; int i; for (i = 0; i < LOOKUP_BSPLINE_RES; i++) { float x = (float)(i + 0.5) / LOOKUP_BSPLINE_RES; store_weights(x, tp); tp += 4; } store_weights(0, tex); store_weights(1, &tex[4 * (LOOKUP_BSPLINE_RES - 1)]); ActiveTexture(unit); glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA16, LOOKUP_BSPLINE_RES, 0, GL_RGBA, GL_FLOAT, tex); glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_PRIORITY, 1.0); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); ActiveTexture(GL_TEXTURE0);}static const char *bilin_filt_template = "TEX yuv.%c, fragment.texcoord[%c], texture[%c], %s;";#define BICUB_FILT_MAIN(textype) \ /* first y-interpolation */ \ "ADD coord, fragment.texcoord[%c].xyxy, cdelta.xyxw;" \ "ADD coord2, fragment.texcoord[%c].xyxy, cdelta.zyzw;" \ "TEX a.r, coord.xyxy, texture[%c], "textype";" \ "TEX a.g, coord.zwzw, texture[%c], "textype";" \ /* second y-interpolation */ \ "TEX b.r, coord2.xyxy, texture[%c], "textype";" \ "TEX b.g, coord2.zwzw, texture[%c], "textype";" \ "LRP a.b, parmy.b, a.rrrr, a.gggg;" \ "LRP a.a, parmy.b, b.rrrr, b.gggg;" \ /* x-interpolation */ \ "LRP yuv.%c, parmx.b, a.bbbb, a.aaaa;"static const char *bicub_filt_template_2D = "MAD coord.xy, fragment.texcoord[%c], {%f, %f}, {0.5, 0.5};" "TEX parmx, coord.x, texture[%c], 1D;" "MUL cdelta.xz, parmx.rrgg, {-%f, 0, %f, 0};" "TEX parmy, coord.y, texture[%c], 1D;" "MUL cdelta.yw, parmy.rrgg, {0, -%f, 0, %f};" BICUB_FILT_MAIN("2D");static const char *bicub_filt_template_RECT = "ADD coord, fragment.texcoord[%c], {0.5, 0.5};" "TEX parmx, coord.x, texture[%c], 1D;" "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};" "TEX parmy, coord.y, texture[%c], 1D;" "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};" BICUB_FILT_MAIN("RECT");#define CALCWEIGHTS(t, s) \ "MAD "t", {-0.5, 0.1666, 0.3333, -0.3333}, "s", {1, 0, -0.5, 0.5};" \ "MAD "t", "t", "s", {0, 0, -0.5, 0.5};" \ "MAD "t", "t", "s", {-0.6666, 0, 0.8333, 0.1666};" \ "RCP a.x, "t".z;" \ "RCP a.y, "t".w;" \ "MAD "t".xy, "t".xyxy, a.xyxy, {1, 1, 0, 0};" \ "ADD "t".x, "t".xxxx, "s";" \ "SUB "t".y, "t".yyyy, "s";"static const char *bicub_notex_filt_template_2D = "MAD coord.xy, fragment.texcoord[%c], {%f, %f}, {0.5, 0.5};" "FRC coord.xy, coord.xyxy;" CALCWEIGHTS("parmx", "coord.xxxx") "MUL cdelta.xz, parmx.rrgg, {-%f, 0, %f, 0};" CALCWEIGHTS("parmy", "coord.yyyy") "MUL cdelta.yw, parmy.rrgg, {0, -%f, 0, %f};" BICUB_FILT_MAIN("2D");static const char *bicub_notex_filt_template_RECT = "ADD coord, fragment.texcoord[%c], {0.5, 0.5};" "FRC coord.xy, coord.xyxy;" CALCWEIGHTS("parmx", "coord.xxxx") "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};" CALCWEIGHTS("parmy", "coord.yyyy") "MUL cdelta.yw, parmy.rrgg, {0, -1, 0, 1};" BICUB_FILT_MAIN("RECT");#define BICUB_X_FILT_MAIN(textype) \ "ADD coord, fragment.texcoord[%c].xyxy, cdelta.xyxw;" \ "ADD coord2, fragment.texcoord[%c].xyxy, cdelta.zyzw;" \ "TEX a.r, coord, texture[%c], "textype";" \ "TEX b.r, coord2, texture[%c], "textype";" \ /* x-interpolation */ \ "LRP yuv.%c, parmx.b, a.rrrr, b.rrrr;"static const char *bicub_x_filt_template_2D = "MAD coord.x, fragment.texcoord[%c], {%f, %f}, {0.5, 0.5};" "TEX parmx, coord, texture[%c], 1D;" "MUL cdelta.xz, parmx.rrgg, {-%f, 0, %f, 0};" BICUB_X_FILT_MAIN("2D");static const char *bicub_x_filt_template_RECT = "ADD coord.x, fragment.texcoord[%c], {0.5, 0.5};" "TEX parmx, coord, texture[%c], 1D;" "MUL cdelta.xz, parmx.rrgg, {-1, 0, 1, 0};" BICUB_X_FILT_MAIN("RECT");static const char *yuv_prog_template = "PARAM ycoef = {%.4f, %.4f, %.4f};" "PARAM ucoef = {%.4f, %.4f, %.4f};" "PARAM vcoef = {%.4f, %.4f, %.4f};" "PARAM offsets = {%.4f, %.4f, %.4f};" "TEMP res;" "MAD res.rgb, yuv.rrrr, ycoef, offsets;" "MAD res.rgb, yuv.gggg, ucoef, res;" "MAD result.color.rgb, yuv.bbbb, vcoef, res;" "END";static const char *yuv_pow_prog_template = "PARAM ycoef = {%.4f, %.4f, %.4f};" "PARAM ucoef = {%.4f, %.4f, %.4f};" "PARAM vcoef = {%.4f, %.4f, %.4f};" "PARAM offsets = {%.4f, %.4f, %.4f};" "PARAM gamma = {%.4f, %.4f, %.4f};" "TEMP res;" "MAD res.rgb, yuv.rrrr, ycoef, offsets;" "MAD res.rgb, yuv.gggg, ucoef, res;" "MAD_SAT res.rgb, yuv.bbbb, vcoef, res;" "POW result.color.r, res.r, gamma.r;" "POW result.color.g, res.g, gamma.g;" "POW result.color.b, res.b, gamma.b;" "END";static const char *yuv_lookup_prog_template = "PARAM ycoef = {%.4f, %.4f, %.4f, 0};" "PARAM ucoef = {%.4f, %.4f, %.4f, 0};" "PARAM vcoef = {%.4f, %.4f, %.4f, 0};" "PARAM offsets = {%.4f, %.4f, %.4f, 0.125};" "TEMP res;" "MAD res, yuv.rrrr, ycoef, offsets;" "MAD res.rgb, yuv.gggg, ucoef, res;" "MAD res.rgb, yuv.bbbb, vcoef, res;" "TEX result.color.r, res.raaa, texture[%c], 2D;" "ADD res.a, res.a, 0.25;" "TEX result.color.g, res.gaaa, texture[%c], 2D;" "ADD res.a, res.a, 0.25;" "TEX result.color.b, res.baaa, texture[%c], 2D;" "END";
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?