示例#1
0
void OpenGL_Blitter::Blit(MDFN_Surface *src_surface, const MDFN_Rect *src_rect, const MDFN_Rect *dest_rect, const MDFN_Rect *original_src_rect, int InterlaceField, int UsingIP, int rotated)
{
 MDFN_Rect tex_src_rect = *src_rect;
 float src_coords[4][2];
 int dest_coords[4][2];
 unsigned int tmpwidth;
 unsigned int tmpheight;
 uint32 *src_pixies;

 if(shader)
 {
  if(shader->ShaderNeedsBTIP())
   UsingIP = VIDEOIP_BILINEAR;
  else
   UsingIP = VIDEOIP_OFF;
 }

 if(src_rect->w == 0 || src_rect->h == 0 || dest_rect->w == 0 || dest_rect->h == 0 || original_src_rect->w == 0 || original_src_rect->h == 0)
 {
  printf("[BUG] OpenGL blitting nothing? --- %d:%d %d:%d %d:%d\n", src_rect->w, src_rect->h, dest_rect->w, dest_rect->h, original_src_rect->w, original_src_rect->h);
  return;
 }


 src_pixies = src_surface->pixels + tex_src_rect.x + tex_src_rect.y * src_surface->pitchinpix;
 tex_src_rect.x = 0;
 tex_src_rect.y = 0;

 MakeDestCoords(dest_rect, dest_coords, rotated);

 p_glBindTexture(GL_TEXTURE_2D, textures[0]);
 p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, UsingIP ? GL_LINEAR : GL_NEAREST);
 p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, UsingIP ? GL_LINEAR : GL_NEAREST);

 if(SupportNPOT)
 {
  tmpwidth = src_rect->w;
  tmpheight = src_rect->h;

  if(tmpwidth != last_w || tmpheight != last_h)
  {
   p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tmpwidth, tmpheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   last_w = tmpwidth;
   last_h = tmpheight;
  }
 }
 else
 {
  bool ImageSizeChange = FALSE;

  tmpwidth = round_up_pow2(src_rect->w);
  tmpheight = round_up_pow2(src_rect->h);

  // If the required GL texture size has changed, resize the texture! :b
  if(tmpwidth != round_up_pow2(last_w) || tmpheight != round_up_pow2(last_h))
  {
   p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tmpwidth, tmpheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   ImageSizeChange = TRUE;
  }
 
  // If the dimensions of our image stored in the texture have changed...
  if(src_rect->w != last_w || src_rect->h != last_h)
   ImageSizeChange = TRUE;

  // Only clean up if we're using pixel shaders and/or bilinear interpolation
  if(ImageSizeChange && (shader || UsingIP))
  {
   uint32 neo_dbs = DummyBlackSize;

   if(src_rect->w != tmpwidth && neo_dbs < src_rect->h)
    neo_dbs = src_rect->h;

   if(src_rect->h != tmpheight && neo_dbs < src_rect->w)
    neo_dbs = src_rect->w;

   if(neo_dbs != DummyBlackSize)
   {
    //printf("Realloc: %d\n", neo_dbs);
    if(DummyBlack)
     MDFN_free(DummyBlack);

    if((DummyBlack = (uint32 *)MDFN_calloc(neo_dbs, sizeof(uint32), _("OpenGL dummy black texture data"))))
     DummyBlackSize = neo_dbs;
    else
     DummyBlackSize = 0;
   }

   //printf("Cleanup: %d %d, %d %d\n", src_rect->w, src_rect->h, tmpwidth, tmpheight);

   if(DummyBlack) // If memory allocation failed for some reason, don't clean the texture. :(
   {
    if(src_rect->w < tmpwidth)
    {
     //puts("X");
     p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 1);
     p_glTexSubImage2D(GL_TEXTURE_2D, 0, src_rect->w, 0, 1, src_rect->h, GL_RGBA, GL_UNSIGNED_BYTE, DummyBlack);
    }
    if(src_rect->h < tmpheight)
    {
     //puts("Y");
     p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_rect->w);
     p_glTexSubImage2D(GL_TEXTURE_2D, 0, 0, src_rect->h, src_rect->w, 1, GL_RGBA, GL_UNSIGNED_BYTE, DummyBlack);
    }
   } // end if(DummyBlack)

  }

  last_w = src_rect->w;
  last_h = src_rect->h;
 }

 MakeSourceCoords(&tex_src_rect, src_coords, tmpwidth, tmpheight);

 if(shader)
  shader->ShaderBegin(gl_screen_w, gl_screen_h, src_rect, dest_rect, tmpwidth, tmpheight, round((double)tmpwidth * original_src_rect->w / src_rect->w), round((double)tmpheight * original_src_rect->h / src_rect->h), rotated);

 p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_surface->pitchinpix);

 p_glTexSubImage2D(GL_TEXTURE_2D, 0, tex_src_rect.x, tex_src_rect.y, tex_src_rect.w, tex_src_rect.h, PixelFormat, PixelType, src_pixies);

 //
 // Draw texture
 //
#ifdef MDFN_TRIANGLE_STRIP_TEST
 p_glBegin(GL_TRIANGLE_STRIP);
#else
 p_glBegin(GL_QUADS);
#endif

 if(UsingIP == VIDEOIP_LINEAR_X || UsingIP == VIDEOIP_LINEAR_Y)	// Linear interpolation, on one axis
 {
  DrawLinearIP(UsingIP, rotated, &tex_src_rect, dest_rect, tmpwidth, tmpheight);
 }
 else	// Regular bilinear or no interpolation.
 {
  DrawQuad(src_coords, dest_coords);
 }

 p_glEnd();

 if(shader)
  shader->ShaderEnd();

 if(using_scanlines)
 {
  float yif_offset = 0;
  int yh_shift = 0;

  if(using_scanlines < 0 && InterlaceField >= 0)
  {
   yif_offset = (float)InterlaceField / 512;
   yh_shift = 1;
  }


  p_glEnable(GL_BLEND);

  p_glBindTexture(GL_TEXTURE_2D, textures[1]);
  p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);

  p_glBegin(GL_QUADS);

  p_glTexCoord2f(0.0f, yif_offset + (original_src_rect->h >> yh_shift) / 256.0f);  // Bottom left of our picture.
  p_glVertex2f((signed)dest_coords[3][0], (signed)dest_coords[3][1]);

  p_glTexCoord2f(1.0f, yif_offset + (original_src_rect->h >> yh_shift) / 256.0f); // Bottom right of our picture.
  p_glVertex2f((signed)dest_coords[2][0], (signed)dest_coords[2][1]);

  p_glTexCoord2f(1.0f, yif_offset);    // Top right of our picture.
  p_glVertex2f((signed)dest_coords[1][0], (signed)dest_coords[1][1]);

  p_glTexCoord2f(0.0f, yif_offset);     // Top left of our picture.
  p_glVertex2f((signed)dest_coords[0][0], (signed)dest_coords[0][1]);

  p_glEnd();
  p_glDisable(GL_BLEND);
 }

 //if(1)
 //{
 // p_glAccum(GL_MULT, 0.99);
 // p_glAccum(GL_ACCUM, 1 - 0.99);
 // p_glAccum(GL_RETURN, 1.0);
 //}
}
示例#2
0
void BlitOpenGL(MDFN_Surface *src_surface, const MDFN_Rect *src_rect, const MDFN_Rect *dest_rect, const MDFN_Rect *original_src_rect)
{
 MDFN_Rect tex_src_rect = *src_rect;
 float src_coords[4][2];
 int dest_coords[4][2];
 unsigned int tmpwidth;
 unsigned int tmpheight;
 uint32 *src_pixies;

 src_pixies = src_surface->pixels + tex_src_rect.x + tex_src_rect.y * src_surface->pitchinpix;
 tex_src_rect.x = 0;
 tex_src_rect.y = 0;

 MakeDestCoords(dest_rect, dest_coords);

 p_glBindTexture(GL_TEXTURE_2D, textures[0]);

 if(SupportNPOT)
 {
  tmpwidth = src_rect->w;
  tmpheight = src_rect->h;

  if(tmpwidth != last_w || tmpheight != last_h)
  {
   p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tmpwidth, tmpheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   last_w = tmpwidth;
   last_h = tmpheight;
  }
 }
 else
 {
  bool ImageSizeChange = FALSE;

  tmpwidth = round_up_pow2(src_rect->w);
  tmpheight = round_up_pow2(src_rect->h);

  // If the required GL texture size has changed, resize the texture! :b
  if(tmpwidth != round_up_pow2(last_w) || tmpheight != round_up_pow2(last_h))
  {
   p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tmpwidth, tmpheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   ImageSizeChange = TRUE;
  }
 
  // If the dimensions of our image stored in the texture have changed...
  if(src_rect->w != last_w || src_rect->h != last_h)
   ImageSizeChange = TRUE;

  // Only clean up if we're using pixel shaders and/or bilinear interpolation
  if(ImageSizeChange && (UsingShader || UsingIP))
  {
   uint32 neo_dbs = DummyBlackSize;

   if(src_rect->w != tmpwidth && neo_dbs < src_rect->h)
    neo_dbs = src_rect->h;

   if(src_rect->h != tmpheight && neo_dbs < src_rect->w)
    neo_dbs = src_rect->w;

   if(neo_dbs != DummyBlackSize)
   {
    //printf("Realloc: %d\n", neo_dbs);
    if(DummyBlack)
     MDFN_free(DummyBlack);

    if((DummyBlack = (uint32 *)MDFN_calloc(neo_dbs, sizeof(uint32), _("OpenGL dummy black texture data"))))
     DummyBlackSize = neo_dbs;
    else
     DummyBlackSize = 0;
   }

   //printf("Cleanup: %d %d, %d %d\n", src_rect->w, src_rect->h, tmpwidth, tmpheight);

   if(DummyBlack) // If memory allocation failed for some reason, don't clean the texture. :(
   {
    if(src_rect->w < tmpwidth)
    {
     //puts("X");
     p_glPixelStorei(GL_UNPACK_ROW_LENGTH, 1);
     p_glTexSubImage2D(GL_TEXTURE_2D, 0, src_rect->w, 0, 1, src_rect->h, GL_RGBA, GL_UNSIGNED_BYTE, DummyBlack);
    }
    if(src_rect->h < tmpheight)
    {
     //puts("Y");
     p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_rect->w);
     p_glTexSubImage2D(GL_TEXTURE_2D, 0, 0, src_rect->h, src_rect->w, 1, GL_RGBA, GL_UNSIGNED_BYTE, DummyBlack);
    }
   } // end if(DummyBlack)

  }

  last_w = src_rect->w;
  last_h = src_rect->h;
 }

 MakeSourceCoords(&tex_src_rect, src_coords, tmpwidth, tmpheight);

 #if MDFN_WANT_OPENGL_SHADERS
 if(UsingShader)
  ShaderBegin(src_rect, dest_rect, tmpwidth, tmpheight);
 #endif

 p_glPixelStorei(GL_UNPACK_ROW_LENGTH, src_surface->pitchinpix);

 p_glTexSubImage2D(GL_TEXTURE_2D, 0, tex_src_rect.x, tex_src_rect.y, tex_src_rect.w, tex_src_rect.h, PixelFormat, PixelType, src_pixies);

 //
 // Draw texture
 //
 p_glBegin(GL_QUADS);

 if(UsingIP == VIDEOIP_LINEAR_X || UsingIP == VIDEOIP_LINEAR_Y)	// Linear interpolation, on one axis
 {
  DrawLinearIP(UsingIP, CurGame->rotated, &tex_src_rect, dest_rect, tmpwidth, tmpheight);
 }
 else	// Regular bilinear or no interpolation.
 {
  DrawQuad(src_coords, dest_coords);
 }

 p_glEnd();

 #if MDFN_WANT_OPENGL_SHADERS
 if(UsingShader)
  ShaderEnd();
 #endif

 if(using_scanlines)
 {
  p_glEnable(GL_BLEND);

  p_glBindTexture(GL_TEXTURE_2D, textures[1]);
  p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);

  p_glBegin(GL_QUADS);

  p_glTexCoord2f(0.0f, 1.0f * original_src_rect->h / 256);  // Bottom left of our picture.
  p_glVertex2f((signed)dest_coords[3][0], (signed)dest_coords[3][1]);

  p_glTexCoord2f(1.0f, 1.0f * original_src_rect->h / 256); // Bottom right of our picture.
  p_glVertex2f((signed)dest_coords[2][0], (signed)dest_coords[2][1]);

  p_glTexCoord2f(1.0f, 0.0f);    // Top right of our picture.
  p_glVertex2f((signed)dest_coords[1][0], (signed)dest_coords[1][1]);

  p_glTexCoord2f(0.0f, 0.0f);     // Top left of our picture.
  p_glVertex2f((signed)dest_coords[0][0], (signed)dest_coords[0][1]);

  p_glEnd();
  p_glDisable(GL_BLEND);
 }

 //if(1)
 //{
 // p_glAccum(GL_MULT, 0.99);
 // p_glAccum(GL_ACCUM, 1 - 0.99);
 // p_glAccum(GL_RETURN, 1.0);
 //}
}