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 + -
显示快捷键?