Ejemplo n.º 1
0
/* Copy bitmap->memory to texture memory */
static void d3d_sync_bitmap_texture(ALLEGRO_BITMAP *bitmap,
   int x, int y, int width, int height)
{
   D3DLOCKED_RECT locked_rect;
   RECT rect;
   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
   LPDIRECT3DTEXTURE9 texture;

   rect.left = x;
   rect.top = y;
   rect.right = x + width;
   rect.bottom = y + height;

   if (_al_d3d_render_to_texture_supported())
      texture = d3d_bmp->system_texture;
   else
      texture = d3d_bmp->video_texture;

   if (texture->LockRect(0, &locked_rect, &rect, 0) == D3D_OK) {
	   _al_convert_bitmap_data(bitmap->memory, bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format),
		  locked_rect.pBits, bitmap->format, locked_rect.Pitch,
		  x, y, 0, 0, width, height);
	   /* Copy an extra row and column so the texture ends nicely */
	   if (rect.bottom > bitmap->h) {
		  _al_convert_bitmap_data(
			 bitmap->memory,
			 bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format),
			 locked_rect.pBits,
			 bitmap->format, locked_rect.Pitch,
			 0, bitmap->h-1,
			 0, height,
			 width, 1);
	   }
	   if (rect.right > bitmap->w) {
		  _al_convert_bitmap_data(
			 bitmap->memory,
			 bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format),
			 locked_rect.pBits,
			 bitmap->format, locked_rect.Pitch,
			 bitmap->w-1, 0,
			 width, 0,
			 1, height);
	   }
	   if (rect.bottom > bitmap->h && rect.right > bitmap->w) {
		  _al_convert_bitmap_data(
			 bitmap->memory,
			 bitmap->format, bitmap->w*al_get_pixel_size(bitmap->format),
			 locked_rect.pBits,
			 bitmap->format, locked_rect.Pitch,
			 bitmap->w-1, bitmap->h-1,
			 width, height,
			 1, 1);
	   }
	   texture->UnlockRect(0);
   }
   else {
      ALLEGRO_ERROR("d3d_sync_bitmap_texture: Couldn't lock texture to upload.\n");
   }
}
Ejemplo n.º 2
0
static void ogl_lock_region_nonbb_readwrite_nonfbo(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format)
{
   /* No FBO - fallback to reading the entire texture */
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(ogl_bitmap->true_w, pixel_size);
   GLenum e;
   (void) w;

   ogl_bitmap->lock_buffer = al_malloc(pitch * ogl_bitmap->true_h);

   glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture);
   glGetTexImage(GL_TEXTURE_2D, 0,
      get_glformat(format, 2),
      get_glformat(format, 1),
      ogl_bitmap->lock_buffer);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glGetTexImage for format %s failed (%s).\n",
         _al_format_name(format), _al_gl_error_string(e));
   }

   bitmap->locked_region.data = ogl_bitmap->lock_buffer +
      pitch * (gl_y + h - 1) + pixel_size * x;
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
}
Ejemplo n.º 3
0
static void ogl_lock_region_nonbb_readwrite_fbo(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format)
{
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(w, pixel_size);
   GLint old_fbo;
   GLenum e;

   glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &old_fbo);

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ogl_bitmap->fbo_info->fbo);

   ogl_bitmap->lock_buffer = al_malloc(pitch * h);

   glReadPixels(x, gl_y, w, h,
      get_glformat(format, 2),
      get_glformat(format, 1),
      ogl_bitmap->lock_buffer);

   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glReadPixels for format %s failed (%s).\n",
         _al_format_name(format), _al_gl_error_string(e));
   }

   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, old_fbo);

   bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1);
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
}
Ejemplo n.º 4
0
bool _al_ogl_resize_backbuffer(ALLEGRO_BITMAP_OGL *b, int w, int h)
{
   int pitch;
         
   pitch = w * al_get_pixel_size(b->bitmap.format);

   b->bitmap.w = w;
   b->bitmap.h = h;
   b->bitmap.pitch = pitch;
   b->bitmap.cl = 0;
   b->bitmap.ct = 0;
   b->bitmap.cr_excl = w;
   b->bitmap.cb_excl = h;

   /* There is no texture associated with the backbuffer so no need to care
    * about texture size limitations. */
   b->true_w = w;
   b->true_h = h;

#if !defined(ALLEGRO_IPHONE) && !defined(ALLEGRO_GP2XWIZ)
   b->bitmap.memory = NULL;
#else
   /* iPhone/Wiz ports still expect the buffer to be present. */
   {
      /* FIXME: lazily manage memory */
      size_t bytes = pitch * h;
      al_free(b->bitmap.memory);
      b->bitmap.memory = al_calloc(1, bytes);
   }
#endif

   return true;
}
Ejemplo n.º 5
0
ALLEGRO_BITMAP_OGL* _al_ogl_create_backbuffer(ALLEGRO_DISPLAY *disp)
{
   ALLEGRO_BITMAP_OGL *ogl_backbuffer;
   ALLEGRO_BITMAP *backbuffer;
   ALLEGRO_STATE backup;
   int format;

   ALLEGRO_DEBUG("Creating backbuffer\n");

   al_store_state(&backup, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);

   // FIXME: _al_deduce_color_format would work fine if the display paramerers
   // are filled in, for WIZ and IPOD
#ifdef ALLEGRO_GP2XWIZ
   format = ALLEGRO_PIXEL_FORMAT_RGB_565; /* Only support display format */
#elif defined ALLEGRO_IPHONE
   format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE;
   // TODO: This one is also supported
   //format = ALLEGRO_PIXEL_FORMAT_RGB_565;
#else
   format = _al_deduce_color_format(&disp->extra_settings);
   /* Eww. No OpenGL hardware in the world does that - let's just
    * switch to some default.
    */
   if (al_get_pixel_size(format) == 3) {
      /* Or should we use RGBA? Maybe only if not Nvidia cards? */
      format = ALLEGRO_PIXEL_FORMAT_ABGR_8888;
   }
#endif
   ALLEGRO_TRACE_CHANNEL_LEVEL("display", 1)("Deduced format %s for backbuffer.\n",
      _al_pixel_format_name(format));

   /* Now that the display backbuffer has a format, update extra_settings so
    * the user can query it back.
    */
   _al_set_color_components(format, &disp->extra_settings, ALLEGRO_REQUIRE);
   disp->backbuffer_format = format;

   ALLEGRO_DEBUG("Creating backbuffer bitmap\n");
   al_set_new_bitmap_format(format);
   /* Using ALLEGRO_NO_PRESERVE_TEXTURE prevents extra memory being allocated */
   al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP | ALLEGRO_NO_PRESERVE_TEXTURE);
   backbuffer = _al_ogl_create_bitmap(disp, disp->w, disp->h);
   al_restore_state(&backup);

   if (!backbuffer) {
      ALLEGRO_DEBUG("Backbuffer bitmap creation failed.\n");
      return NULL;
   }
   
   ALLEGRO_TRACE_CHANNEL_LEVEL("display", 1)(
      "Created backbuffer bitmap (actual format: %s)\n",
      _al_pixel_format_name(backbuffer->format));

   ogl_backbuffer = (ALLEGRO_BITMAP_OGL*)backbuffer;
   ogl_backbuffer->is_backbuffer = 1;
   backbuffer->display = disp;

   return ogl_backbuffer;
}
Ejemplo n.º 6
0
static void ogl_unlock_region_nonbb_fbo_writeonly(ALLEGRO_BITMAP *bitmap,
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap, int gl_y, int orig_format)
{
   const int lock_format = bitmap->locked_region.format;
   const int orig_pixel_size = al_get_pixel_size(orig_format);
   const int dst_pitch = bitmap->lock_w * orig_pixel_size;
   unsigned char * const tmpbuf = al_malloc(dst_pitch * bitmap->lock_h);
   GLenum e;

   _al_convert_bitmap_data(
      ogl_bitmap->lock_buffer,
      bitmap->locked_region.format,
      -bitmap->locked_region.pitch,
      tmpbuf,
      orig_format,
      dst_pitch,
      0, 0, 0, 0,
      bitmap->lock_w, bitmap->lock_h);

   glTexSubImage2D(GL_TEXTURE_2D, 0,
      bitmap->lock_x, gl_y,
      bitmap->lock_w, bitmap->lock_h,
      get_glformat(orig_format, 2),
      get_glformat(orig_format, 1),
      tmpbuf);
   e = glGetError();
   if (e) {
      ALLEGRO_ERROR("glTexSubImage2D for format %d failed (%s).\n",
         lock_format, _al_gl_error_string(e));
   }

   al_free(tmpbuf);
}
Ejemplo n.º 7
0
static bool ogl_lock_region_backbuffer(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format, int flags)
{
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(w, pixel_size);
   GLenum e;

   ogl_bitmap->lock_buffer = al_malloc(pitch * h);
   if (ogl_bitmap->lock_buffer == NULL) {
      return false;
   }

   if (!(flags & ALLEGRO_LOCK_WRITEONLY)) {
      glReadPixels(x, gl_y, w, h,
         get_glformat(format, 2),
         get_glformat(format, 1),
         ogl_bitmap->lock_buffer);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glReadPixels for format %s failed (%s).\n",
            _al_pixel_format_name(format), _al_gl_error_string(e));
         al_free(ogl_bitmap->lock_buffer);
         ogl_bitmap->lock_buffer = NULL;
         return false;
      }
   }

   bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1);
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
   return true;
}
Ejemplo n.º 8
0
void _al_convert_bitmap_data(
   void *src, int src_format, int src_pitch,
   void *dst, int dst_format, int dst_pitch,
   int sx, int sy, int dx, int dy, int width, int height)
{
   ASSERT(src);
   ASSERT(dst);
   ASSERT(_al_pixel_format_is_real(dst_format));

   /* Use memcpy if no conversion is needed. */
   if (src_format == dst_format) {
      int y;
      int size = al_get_pixel_size(src_format);
      char *src_ptr = ((char *)src) + sy * src_pitch + sx * size;
      char *dst_ptr = ((char *)dst) + dy * dst_pitch + dx * size;
      width *= size;
      for (y = 0; y < height; y++) {
         memcpy(dst_ptr, src_ptr, width);
         src_ptr += src_pitch;
         dst_ptr += dst_pitch;
      }
      return;
   }

   (_al_convert_funcs[src_format][dst_format])(src, src_pitch,
      dst, dst_pitch, sx, sy, dx, dy, width, height);
}
Ejemplo n.º 9
0
/* Creates a memory bitmap.
 */
static ALLEGRO_BITMAP *_al_create_memory_bitmap(int w, int h)
{
   ALLEGRO_BITMAP *bitmap;
   int pitch;
   int format = al_get_new_bitmap_format();

   format = _al_get_real_pixel_format(al_get_current_display(), format);

   bitmap = al_calloc(1, sizeof *bitmap);
   bitmap->size = sizeof(*bitmap);

   pitch = w * al_get_pixel_size(format);

   bitmap->vt = NULL;
   bitmap->format = format;
   bitmap->flags = (al_get_new_bitmap_flags() | ALLEGRO_MEMORY_BITMAP) &
      ~ALLEGRO_VIDEO_BITMAP;
   bitmap->w = w;
   bitmap->h = h;
   bitmap->pitch = pitch;
   bitmap->display = NULL;
   bitmap->locked = false;
   bitmap->cl = bitmap->ct = 0;
   bitmap->cr_excl = w;
   bitmap->cb_excl = h;
   al_identity_transform(&bitmap->transform);
   bitmap->parent = NULL;
   bitmap->xofs = bitmap->yofs = 0;
   bitmap->memory = al_malloc(pitch * h);
   bitmap->preserve_texture = !(al_get_new_bitmap_flags() & ALLEGRO_NO_PRESERVE_TEXTURE);
   return bitmap;
}
Ejemplo n.º 10
0
void m_draw_scaled_backbuffer(int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, MBITMAP *dest)
{
	ALLEGRO_BITMAP *old_target = al_get_target_bitmap();
	int old_format = al_get_new_bitmap_format();
	al_set_new_bitmap_format(al_get_bitmap_format(al_get_backbuffer(display)));
	MBITMAP *tmp = m_create_bitmap(sw, sh);
	int scr_w = al_get_display_width(display);
	int scr_h = al_get_display_height(display);
	if (sx+sw > scr_w) {
		sw = scr_w-sx;
	}
	else if (sx < 0) {
		sw -= sx;
		sx = 0;
	}
	if (sy+sh > scr_h) {
		sh = scr_h-sy;
	}
	else if (sy < 0) {
		sh -= sy;
		sy = 0;
	}

#if defined ALLEGRO_RASPBERRYPI || defined ALLEGRO_IPHONE || defined ALLEGRO_ANDROID
	ALLEGRO_LOCKED_REGION *lr1 = al_lock_bitmap(tmp->bitmap, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);
	ALLEGRO_LOCKED_REGION *lr2 = al_lock_bitmap_region(
		al_get_backbuffer(display),
		sx, sy, sw, sh,
		ALLEGRO_PIXEL_FORMAT_ANY,
		ALLEGRO_LOCK_READONLY
	);
	int pixel_size = al_get_pixel_size(al_get_bitmap_format(al_get_backbuffer(display)));
	for (int y = 0; y < sh; y++) {
		uint8_t *d1 = (uint8_t *)lr1->data + lr1->pitch * y;
		uint8_t *d2 = (uint8_t *)lr2->data + lr2->pitch * y;
		memcpy(d1, d2, pixel_size*sw);
	}
	al_unlock_bitmap(tmp->bitmap);
	al_unlock_bitmap(al_get_backbuffer(display));
#else
	m_set_target_bitmap(tmp);
	al_draw_bitmap_region(al_get_backbuffer(display), sx, sy, sw, sh, 0, 0, 0);
#endif
	m_set_target_bitmap(dest);
	al_draw_scaled_bitmap(
		tmp->bitmap,
		0, 0, sw, sh,
		dx, dy, dw, dh,
		0
	);
	m_destroy_bitmap(tmp);
	al_set_target_bitmap(old_target);
	al_set_new_bitmap_format(old_format);
}
Ejemplo n.º 11
0
/* We use al_get_display_format() as a hint for the preferred RGB ordering when
 * nothing else is specified.
 */
static bool try_display_format(ALLEGRO_DISPLAY *display, int *format)
{
   int best_format;
   int bytes;

   if (!display) {
      return false;
   }

   best_format = al_get_display_format(display);
   if (!_al_pixel_format_is_real(best_format))
      return false;

   bytes = al_get_pixel_size(*format);
   if (bytes && bytes != al_get_pixel_size(best_format))
      return false;

   if (_al_pixel_format_has_alpha(*format) &&
      !_al_pixel_format_has_alpha(best_format))
   {
      switch (best_format) {
         case ALLEGRO_PIXEL_FORMAT_RGBX_8888:
            *format = ALLEGRO_PIXEL_FORMAT_RGBA_8888;
            return true;
         case ALLEGRO_PIXEL_FORMAT_XRGB_8888:
             *format = ALLEGRO_PIXEL_FORMAT_ARGB_8888;
            return true;
         case ALLEGRO_PIXEL_FORMAT_XBGR_8888:
            *format = ALLEGRO_PIXEL_FORMAT_ABGR_8888;
            return true;
         default:
            return false;
      }
   }
   *format = best_format;
   return true;
}
Ejemplo n.º 12
0
static void ogl_lock_region_nonbb_writeonly(
   ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap,
   int x, int gl_y, int w, int h, int format)
{
   const int pixel_size = al_get_pixel_size(format);
   const int pitch = ogl_pitch(w, pixel_size);
   (void) x;
   (void) gl_y;

   ogl_bitmap->lock_buffer = al_malloc(pitch * h);
   bitmap->locked_region.data = ogl_bitmap->lock_buffer + pitch * (h - 1);
   bitmap->locked_region.format = format;
   bitmap->locked_region.pitch = -pitch;
   bitmap->locked_region.pixel_size = pixel_size;
}
Ejemplo n.º 13
0
/* Creates a memory bitmap.
 */
static ALLEGRO_BITMAP *create_memory_bitmap(ALLEGRO_DISPLAY *current_display,
   int w, int h, int format, int flags)
{
   ALLEGRO_BITMAP *bitmap;
   int pitch;

   if (_al_pixel_format_is_video_only(format)) {
      /* Can't have a video-only memory bitmap... */
      return NULL;
   }

   format = _al_get_real_pixel_format(current_display, format);

   bitmap = al_calloc(1, sizeof *bitmap);

   pitch = w * al_get_pixel_size(format);

   bitmap->vt = NULL;
   bitmap->_format = format;

   /* If this is really a video bitmap, we add it to the list of to
    * be converted bitmaps.
    */
   bitmap->_flags = flags | ALLEGRO_MEMORY_BITMAP;
   bitmap->_flags &= ~ALLEGRO_VIDEO_BITMAP;
   bitmap->w = w;
   bitmap->h = h;
   bitmap->pitch = pitch;
   bitmap->_display = NULL;
   bitmap->locked = false;
   bitmap->cl = bitmap->ct = 0;
   bitmap->cr_excl = w;
   bitmap->cb_excl = h;
   al_identity_transform(&bitmap->transform);
   al_identity_transform(&bitmap->inverse_transform);
   bitmap->inverse_transform_dirty = false;
   al_identity_transform(&bitmap->proj_transform);
   al_orthographic_transform(&bitmap->proj_transform, 0, 0, -1.0, w, h, 1.0);
   bitmap->parent = NULL;
   bitmap->xofs = bitmap->yofs = 0;
   bitmap->memory = al_malloc(pitch * h);
   
   _al_register_convert_bitmap(bitmap);
   return bitmap;
}
Ejemplo n.º 14
0
/* Copy texture memory to bitmap->memory */
static void d3d_sync_bitmap_memory(ALLEGRO_BITMAP *bitmap)
{
   D3DLOCKED_RECT locked_rect;
   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;
   LPDIRECT3DTEXTURE9 texture;

   if (_al_d3d_render_to_texture_supported())
      texture = d3d_bmp->system_texture;
   else
      texture = d3d_bmp->video_texture;

   if (texture->LockRect(0, &locked_rect, NULL, 0) == D3D_OK) {
      _al_convert_bitmap_data(locked_rect.pBits, bitmap->format, locked_rect.Pitch,
         bitmap->memory, bitmap->format, al_get_pixel_size(bitmap->format)*bitmap->w,
         0, 0, 0, 0, bitmap->w, bitmap->h);
      texture->UnlockRect(0);
   }
   else {
      ALLEGRO_ERROR("d3d_sync_bitmap_memory: Couldn't lock texture.\n");
   }
}
Ejemplo n.º 15
0
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap,
   int x, int y, int w, int h, int format, int flags)
{
   ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra;
   const GLint gl_y = bitmap->h - y - h;
   ALLEGRO_DISPLAY *disp;
   ALLEGRO_DISPLAY *old_disp = NULL;
   ALLEGRO_BITMAP *old_target = al_get_target_bitmap();
   GLenum e;
   bool ok;
   bool restore_fbo = false;

   if (format == ALLEGRO_PIXEL_FORMAT_ANY) {
      /* Never pick compressed formats with ANY, as it interacts weirdly with
       * existing code (e.g. al_get_pixel_size() etc) */
      int bitmap_format = al_get_bitmap_format(bitmap);
      if (_al_pixel_format_is_compressed(bitmap_format)) {
         // XXX Get a good format from the driver?
         format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE;
      }
      else {
         format = bitmap_format;
      }
   }

   disp = al_get_current_display();
   format = _al_get_real_pixel_format(disp, format);

   /* Change OpenGL context if necessary. */
   if (!disp ||
      (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false &&
       _al_get_bitmap_display(bitmap) != disp))
   {
      old_disp = disp;
      _al_set_current_display_only(_al_get_bitmap_display(bitmap));
   }

   ok = true;

   /* Set up the pixel store state.  We will need to match it when unlocking.
    * There may be other pixel store state we should be setting.
    * See also pitfalls 7 & 8 from:
    * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
    */
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
   {
      const int pixel_size = al_get_pixel_size(format);
      const int pixel_alignment = ogl_pixel_alignment(pixel_size);
      glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n",
            pixel_alignment, _al_gl_error_string(e));
         ok = false;
      }
   }

   if (ok) {
      if (ogl_bitmap->is_backbuffer) {
         ALLEGRO_DEBUG("Locking backbuffer\n");
         ok = ogl_lock_region_backbuffer(bitmap, ogl_bitmap,
            x, gl_y, w, h, format, flags);
      }
      else if (flags & ALLEGRO_LOCK_WRITEONLY) {
         ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n");
         ok = ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap,
            x, gl_y, w, h, format);
      }
      else {
         ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n");
         ok = ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap,
            x, gl_y, w, h, format, &restore_fbo);
      }
   }

   glPopClientAttrib();

   /* Restore state after switching FBO. */
   if (restore_fbo) {
      if (!old_target) {
         /* Old target was NULL; release the context. */
         _al_set_current_display_only(NULL);
      }
      else if (!_al_get_bitmap_display(old_target)) {
         /* Old target was memory bitmap; leave the current display alone. */
      }
      else if (old_target != bitmap) {
         /* Old target was another OpenGL bitmap. */
         _al_ogl_setup_fbo(_al_get_bitmap_display(old_target), old_target);
      }
   }

   ASSERT(al_get_target_bitmap() == old_target);

   if (old_disp != NULL) {
      _al_set_current_display_only(old_disp);
   }

   if (ok) {
      return &bitmap->locked_region;
   }

   ALLEGRO_ERROR("Failed to lock region\n");
   ASSERT(ogl_bitmap->lock_buffer == NULL);
   return NULL;
}
Ejemplo n.º 16
0
static void ogl_unlock_region_non_readonly(ALLEGRO_BITMAP *bitmap,
   ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap)
{
   const int lock_format = bitmap->locked_region.format;
   const int gl_y = bitmap->h - bitmap->lock_y - bitmap->lock_h;
   ALLEGRO_DISPLAY *old_disp = NULL;
   ALLEGRO_DISPLAY *disp;
   int orig_format;
   bool biased_alpha = false;
   GLenum e;

   disp = al_get_current_display();
   orig_format = _al_get_real_pixel_format(disp, _al_get_bitmap_memory_format(bitmap));

   /* Change OpenGL context if necessary. */
   if (!disp ||
      (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false &&
       _al_get_bitmap_display(bitmap) != disp))
   {
      old_disp = disp;
      _al_set_current_display_only(_al_get_bitmap_display(bitmap));
   }

   /* Keep this in sync with ogl_lock_region. */
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
   {
      const int lock_pixel_size = al_get_pixel_size(lock_format);
      const int pixel_alignment = ogl_pixel_alignment(lock_pixel_size);
      glPixelStorei(GL_UNPACK_ALIGNMENT, pixel_alignment);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glPixelStorei(GL_UNPACK_ALIGNMENT, %d) failed (%s).\n",
            pixel_alignment, _al_gl_error_string(e));
      }
   }
   if (exactly_15bpp(lock_format)) {
      /* OpenGL does not support 15-bpp internal format without an alpha,
       * so when storing such data we must ensure the alpha bit is set.
       */
      glPixelTransferi(GL_ALPHA_BIAS, 1);
      biased_alpha = true;
   }

   if (ogl_bitmap->is_backbuffer) {
      ALLEGRO_DEBUG("Unlocking backbuffer\n");
      ogl_unlock_region_backbuffer(bitmap, ogl_bitmap, gl_y);
   }
   else {
      glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture);
      if (ogl_bitmap->fbo_info) {
         ALLEGRO_DEBUG("Unlocking non-backbuffer (FBO)\n");
         ogl_unlock_region_nonbb_fbo(bitmap, ogl_bitmap, gl_y, orig_format);
      }
      else {
         ALLEGRO_DEBUG("Unlocking non-backbuffer (non-FBO)\n");
         ogl_unlock_region_nonbb_nonfbo(bitmap, ogl_bitmap, gl_y);
      }

      /* If using FBOs, we need to regenerate mipmaps explicitly now. */
      /* XXX why don't we check ogl_bitmap->fbo_info? */
      if ((al_get_bitmap_flags(bitmap) & ALLEGRO_MIPMAP) &&
         al_get_opengl_extension_list()->ALLEGRO_GL_EXT_framebuffer_object)
      {
         glGenerateMipmapEXT(GL_TEXTURE_2D);
         e = glGetError();
         if (e) {
            ALLEGRO_ERROR("glGenerateMipmapEXT for texture %d failed (%s).\n",
               ogl_bitmap->texture, _al_gl_error_string(e));
         }
      }
   }

   if (biased_alpha) {
      glPixelTransferi(GL_ALPHA_BIAS, 0);
   }
   glPopClientAttrib();

   if (old_disp) {
      _al_set_current_display_only(old_disp);
   }
}
Ejemplo n.º 17
0
static ALLEGRO_BITMAP *do_create_bitmap(int w, int h)
{
   ALLEGRO_BITMAP *bitmap;
   ALLEGRO_BITMAP **back;
   ALLEGRO_SYSTEM *system = al_get_system_driver();
   ALLEGRO_DISPLAY *current_display = al_get_current_display();
   int64_t mul;

   /* Reject bitmaps where a calculation pixel_size*w*h would overflow
    * int.  Supporting such bitmaps would require a lot more work.
    */
   mul = 4 * (int64_t) w * (int64_t) h;
   if (mul > (int64_t) INT_MAX) {
      ALLEGRO_WARN("Rejecting %dx%d bitmap\n", w, h);
      return NULL;
   }

   if ((al_get_new_bitmap_flags() & ALLEGRO_MEMORY_BITMAP) ||
         (!current_display || !current_display->vt || current_display->vt->create_bitmap == NULL) ||
         (system->displays._size < 1)) {
      return _al_create_memory_bitmap(w, h);
   }

   /* Else it's a display bitmap */

   bitmap = current_display->vt->create_bitmap(current_display, w, h);
   if (!bitmap) {
      ALLEGRO_ERROR("failed to create display bitmap\n");
      return NULL;
   }

   /* XXX the ogl_display driver sets some of these variables. It's not clear
    * who should be responsible for setting what.
    * The pitch must be set by the driver.
    */
   bitmap->display = current_display;
   bitmap->w = w;
   bitmap->h = h;
   bitmap->locked = false;
   bitmap->cl = 0;
   bitmap->ct = 0;
   bitmap->cr_excl = w;
   bitmap->cb_excl = h;
   al_identity_transform(&bitmap->transform);
   bitmap->parent = NULL;
   bitmap->xofs = 0;
   bitmap->yofs = 0;
   bitmap->preserve_texture = !(al_get_new_bitmap_flags() & ALLEGRO_NO_PRESERVE_TEXTURE);

   ASSERT(bitmap->pitch >= w * al_get_pixel_size(bitmap->format));

   /* The display driver should have set the bitmap->memory field if
    * appropriate; video bitmaps may leave it NULL.
    */

   if (!bitmap->vt->upload_bitmap(bitmap)) {
      al_destroy_bitmap(bitmap);
      return NULL;
   }

   /* We keep a list of bitmaps depending on the current display so that we can
    * convert them to memory bimaps when the display is destroyed. */
   back = _al_vector_alloc_back(&current_display->bitmaps);
   *back = bitmap;

   return bitmap;
}
Ejemplo n.º 18
0
ALLEGRO_BITMAP *_al_create_bitmap_params(ALLEGRO_DISPLAY *current_display,
   int w, int h, int format, int flags)
{
   ALLEGRO_SYSTEM *system = al_get_system_driver();
   ALLEGRO_BITMAP *bitmap;
   ALLEGRO_BITMAP **back;
   int64_t mul;
   bool result;

   /* Reject bitmaps where a calculation pixel_size*w*h would overflow
    * int.  Supporting such bitmaps would require a lot more work.
    */
   mul = 4 * (int64_t) w * (int64_t) h;
   if (mul > (int64_t) INT_MAX) {
      ALLEGRO_WARN("Rejecting %dx%d bitmap\n", w, h);
      return NULL;
   }

   if ((flags & ALLEGRO_MEMORY_BITMAP) ||
         !current_display ||
         !current_display->vt ||
         current_display->vt->create_bitmap == NULL ||
         _al_vector_size(&system->displays) < 1)
   {
      if (flags & ALLEGRO_VIDEO_BITMAP)
         return NULL;

      return create_memory_bitmap(current_display, w, h, format, flags);
   }

   /* Else it's a display bitmap */

   bitmap = current_display->vt->create_bitmap(current_display, w, h,
      format, flags);
   if (!bitmap) {
      ALLEGRO_ERROR("failed to create display bitmap\n");
      return NULL;
   }

   bitmap->_display = current_display;
   bitmap->w = w;
   bitmap->h = h;
   bitmap->locked = false;
   bitmap->cl = 0;
   bitmap->ct = 0;
   bitmap->cr_excl = w;
   bitmap->cb_excl = h;
   al_identity_transform(&bitmap->transform);
   al_identity_transform(&bitmap->inverse_transform);
   bitmap->inverse_transform_dirty = false;
   al_identity_transform(&bitmap->proj_transform);
   al_orthographic_transform(&bitmap->proj_transform, 0, 0, -1.0, w, h, 1.0);
   bitmap->parent = NULL;
   bitmap->xofs = 0;
   bitmap->yofs = 0;
   bitmap->_flags |= ALLEGRO_VIDEO_BITMAP;
   bitmap->dirty = !(bitmap->_flags & ALLEGRO_NO_PRESERVE_TEXTURE);

   /* The display driver should have set the bitmap->memory field if
    * appropriate; video bitmaps may leave it NULL.
    */

   ASSERT(bitmap->pitch >= w * al_get_pixel_size(bitmap->_format));
   result = bitmap->vt->upload_bitmap(bitmap);

   if (!result) {
      al_destroy_bitmap(bitmap);
      if (flags & ALLEGRO_VIDEO_BITMAP)
         return NULL;
      /* With ALLEGRO_CONVERT_BITMAP, just use a memory bitmap instead if
      * video failed.
      */
      return create_memory_bitmap(current_display, w, h, format, flags);
   }
   
   /* We keep a list of bitmaps depending on the current display so that we can
    * convert them to memory bimaps when the display is destroyed. */
   back = _al_vector_alloc_back(&current_display->bitmaps);
   *back = bitmap;

   return bitmap;
}
Ejemplo n.º 19
0
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap,
   int x, int y, int w, int h, int format, int flags)
{
   ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra;
   const GLint gl_y = bitmap->h - y - h;
   ALLEGRO_DISPLAY *disp;
   ALLEGRO_DISPLAY *old_disp = NULL;
   GLenum e;

   if (format == ALLEGRO_PIXEL_FORMAT_ANY) {
      format = bitmap->format;
   }

   disp = al_get_current_display();
   format = _al_get_real_pixel_format(disp, format);

   /* Change OpenGL context if necessary. */
   if (!disp ||
      (bitmap->display->ogl_extras->is_shared == false &&
       bitmap->display != disp))
   {
      old_disp = disp;
      _al_set_current_display_only(bitmap->display);
   }

   /* Set up the pixel store state.  We will need to match it when unlocking.
    * There may be other pixel store state we should be setting.
    * See also pitfalls 7 & 8 from:
    * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
    */
   glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
   {
      const int pixel_size = al_get_pixel_size(format);
      const int pixel_alignment = ogl_pixel_alignment(pixel_size);
      glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment);
      e = glGetError();
      if (e) {
         ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n",
            pixel_alignment, _al_gl_error_string(e));
      }
   }

   if (ogl_bitmap->is_backbuffer) {
      ALLEGRO_DEBUG("Locking backbuffer\n");
      ogl_lock_region_backbuffer(bitmap, ogl_bitmap,
         x, gl_y, w, h, format, flags);
   }
   else if (flags & ALLEGRO_LOCK_WRITEONLY) {
      ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n");
      ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap,
         x, gl_y, w, h, format);
   }
   else {
      ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n");
      ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap,
         x, gl_y, w, h, format);
   }

   glPopClientAttrib();

   if (old_disp != NULL) {
      _al_set_current_display_only(old_disp);
   }

   return &bitmap->locked_region;
}
Ejemplo n.º 20
0
/* Function: al_lock_bitmap_region
 */
ALLEGRO_LOCKED_REGION *al_lock_bitmap_region(ALLEGRO_BITMAP *bitmap,
   int x, int y, int width, int height, int format, int flags)
{
   ASSERT(x >= 0);
   ASSERT(y >= 0);
   ASSERT(width >= 0);
   ASSERT(height >= 0);

   /* For sub-bitmaps */
   if (bitmap->parent) {
      x += bitmap->xofs;
      y += bitmap->yofs;
      bitmap = bitmap->parent;
   }

   if (bitmap->locked)
      return NULL;

   ASSERT(x+width <= bitmap->w);
   ASSERT(y+height <= bitmap->h);

   bitmap->lock_x = x;
   bitmap->lock_y = y;
   bitmap->lock_w = width;
   bitmap->lock_h = height;
   bitmap->lock_flags = flags;

   if (bitmap->flags & ALLEGRO_MEMORY_BITMAP) {
      int f = _al_get_real_pixel_format(al_get_current_display(), format);
      if (f < 0) {
         return NULL;
      }
      ASSERT(bitmap->memory);
      if (format == ALLEGRO_PIXEL_FORMAT_ANY || bitmap->format == format || f == bitmap->format) {
         bitmap->locked_region.data = bitmap->memory
            + bitmap->pitch * y + x * al_get_pixel_size(bitmap->format);
         bitmap->locked_region.format = bitmap->format;
         bitmap->locked_region.pitch = bitmap->pitch;
         bitmap->locked_region.pixel_size = al_get_pixel_size(bitmap->format);
      }
      else {
         bitmap->locked_region.pitch = al_get_pixel_size(f) * width;
         bitmap->locked_region.data = al_malloc(bitmap->locked_region.pitch*height);
         bitmap->locked_region.format = f;
         bitmap->locked_region.pixel_size = al_get_pixel_size(f);
         if (!(bitmap->lock_flags & ALLEGRO_LOCK_WRITEONLY)) {
            _al_convert_bitmap_data(
               bitmap->memory, bitmap->format, bitmap->pitch,
               bitmap->locked_region.data, f, bitmap->locked_region.pitch,
               x, y, 0, 0, width, height);
         }
      }
   }
   else {
      if (!bitmap->vt->lock_region(bitmap, x, y, width, height, format, flags)) {
         return NULL;
      }
   }

   bitmap->locked = true;

   return &bitmap->locked_region;
}
Ejemplo n.º 21
0
static ALLEGRO_BITMAP
   *d3d_create_bitmap_from_surface(LPDIRECT3DSURFACE9 surface,
   int format, int flags)
{
   ALLEGRO_BITMAP *bitmap;
   ALLEGRO_BITMAP_D3D *d3d_bmp;
   D3DSURFACE_DESC desc;
   D3DLOCKED_RECT surf_locked_rect;
   D3DLOCKED_RECT sys_locked_rect;
   ALLEGRO_STATE backup;
   unsigned int y;

   if (surface->GetDesc(&desc) != D3D_OK) {
      ALLEGRO_ERROR("d3d_create_bitmap_from_surface: GetDesc failed.\n");
      return NULL;
   }

   if (surface->LockRect(&surf_locked_rect, 0, D3DLOCK_READONLY) != D3D_OK) {
      ALLEGRO_ERROR("d3d_create_bitmap_from_surface: LockRect failed.\n");
      return NULL;
   }

   al_store_state(&backup, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);

   al_set_new_bitmap_format(format);
   al_set_new_bitmap_flags(flags);

   bitmap = al_create_bitmap(desc.Width, desc.Height);
   d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;

   al_restore_state(&backup);

   if (!bitmap) {
      surface->UnlockRect();
      return NULL;
   }

   if (d3d_bmp->system_texture->LockRect(0, &sys_locked_rect, 0, 0) != D3D_OK) {
      surface->UnlockRect();
      al_destroy_bitmap(bitmap);
      ALLEGRO_ERROR("d3d_create_bitmap_from_surface: Lock system texture failed.\n");
      return NULL;
   }

   for (y = 0; y < desc.Height; y++) {
      memcpy(
         ((char*)sys_locked_rect.pBits)+(sys_locked_rect.Pitch*y),
         ((char*)surf_locked_rect.pBits)+(surf_locked_rect.Pitch*y),
         desc.Width*al_get_pixel_size(format)
      );
   }

   surface->UnlockRect();
   d3d_bmp->system_texture->UnlockRect(0);

   if (d3d_bmp->display->device->UpdateTexture(
         (IDirect3DBaseTexture9 *)d3d_bmp->system_texture,
         (IDirect3DBaseTexture9 *)d3d_bmp->video_texture) != D3D_OK) {
      ALLEGRO_ERROR("d3d_create_bitmap_from_texture: Couldn't update texture.\n");
   }

   return bitmap;
}
Ejemplo n.º 22
0
static ALLEGRO_LOCKED_REGION *d3d_lock_region(ALLEGRO_BITMAP *bitmap,
   int x, int y, int w, int h, int format,
   int flags)
{
   ALLEGRO_BITMAP_D3D *d3d_bmp = (ALLEGRO_BITMAP_D3D *)bitmap;

   if (d3d_bmp->display->device_lost)
      return NULL;

   RECT rect;
   DWORD Flags = flags & ALLEGRO_LOCK_READONLY ? D3DLOCK_READONLY : 0;
   int f = _al_get_real_pixel_format(al_get_current_display(), format);
   if (f < 0) {
      return NULL;
   }

   rect.left = x;
   rect.right = x + w;
   rect.top = y;
   rect.bottom = y + h;

   if (d3d_bmp->is_backbuffer) {
      ALLEGRO_DISPLAY_D3D *d3d_disp = (ALLEGRO_DISPLAY_D3D *)bitmap->display;
      if (d3d_disp->render_target->LockRect(&d3d_bmp->locked_rect, &rect, Flags) != D3D_OK) {
         ALLEGRO_ERROR("LockRect failed in d3d_lock_region.\n");
         return NULL;
      }
   }
   else {
      LPDIRECT3DTEXTURE9 texture;
      if (_al_d3d_render_to_texture_supported()) {
         /* 
	  * Sync bitmap->memory with texture
          */
	 bitmap->locked = false;
         _al_d3d_sync_bitmap(bitmap);
	 bitmap->locked = true;
         texture = d3d_bmp->system_texture;
      }
      else {
         texture = d3d_bmp->video_texture;
      }
      if (texture->LockRect(0, &d3d_bmp->locked_rect, &rect, Flags) != D3D_OK) {
         ALLEGRO_ERROR("LockRect failed in d3d_lock_region.\n");
         return NULL;
      }
   }

   if (format == ALLEGRO_PIXEL_FORMAT_ANY || bitmap->format == format || f == bitmap->format) {
      bitmap->locked_region.data = d3d_bmp->locked_rect.pBits;
      bitmap->locked_region.format = bitmap->format;
      bitmap->locked_region.pitch = d3d_bmp->locked_rect.Pitch;
      bitmap->locked_region.pixel_size = al_get_pixel_size(bitmap->format);
   }
   else {
      bitmap->locked_region.pitch = al_get_pixel_size(f) * w;
      bitmap->locked_region.data = al_malloc(bitmap->locked_region.pitch*h);
      bitmap->locked_region.format = f;
      bitmap->locked_region.pixel_size = al_get_pixel_size(bitmap->format);
      if (!(bitmap->lock_flags & ALLEGRO_LOCK_WRITEONLY)) {
         _al_convert_bitmap_data(
            d3d_bmp->locked_rect.pBits, bitmap->format, d3d_bmp->locked_rect.Pitch,
            bitmap->locked_region.data, f, bitmap->locked_region.pitch,
            0, 0, 0, 0, w, h);
      }
   }

   return &bitmap->locked_region;
}