4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2007,2008,2009 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
28 #include "cogl-util.h"
29 #include "cogl-debug.h"
30 #include "cogl-private.h"
31 #include "cogl-bitmap-private.h"
32 #include "cogl-buffer-private.h"
33 #include "cogl-pixel-buffer.h"
34 #include "cogl-context-private.h"
40 CoglHandleObject _parent;
41 CoglPixelFormat format;
51 /* If this is non-null then 'data' is ignored and instead it is
52 fetched from this shared bitmap. */
53 CoglBitmap *shared_bmp;
55 /* If this is non-null then 'data' is treated as an offset into the
56 buffer and map will divert to mapping the buffer */
60 static void _cogl_bitmap_free (CoglBitmap *bmp);
62 COGL_OBJECT_DEFINE (Bitmap, bitmap);
65 _cogl_bitmap_free (CoglBitmap *bmp)
67 g_assert (!bmp->mapped);
68 g_assert (!bmp->bound);
71 cogl_object_unref (bmp->shared_bmp);
74 cogl_object_unref (bmp->buffer);
76 g_slice_free (CoglBitmap, bmp);
80 _cogl_bitmap_convert_premult_status (CoglBitmap *bmp,
81 CoglPixelFormat dst_format)
83 /* Do we need to unpremultiply? */
84 if ((bmp->format & COGL_PREMULT_BIT) > 0 &&
85 (dst_format & COGL_PREMULT_BIT) == 0 &&
86 COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (dst_format))
87 return _cogl_bitmap_unpremult (bmp);
89 /* Do we need to premultiply? */
90 if ((bmp->format & COGL_PREMULT_BIT) == 0 &&
91 COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (bmp->format) &&
92 (dst_format & COGL_PREMULT_BIT) > 0)
93 /* Try premultiplying using imaging library */
94 return _cogl_bitmap_premult (bmp);
100 _cogl_bitmap_copy (CoglBitmap *src_bmp)
103 CoglPixelFormat src_format = cogl_bitmap_get_format (src_bmp);
104 int width = cogl_bitmap_get_width (src_bmp);
105 int height = cogl_bitmap_get_height (src_bmp);
107 _COGL_GET_CONTEXT (ctx, NULL);
110 _cogl_bitmap_new_with_malloc_buffer (ctx,
114 _cogl_bitmap_copy_subregion (src_bmp,
124 _cogl_bitmap_copy_subregion (CoglBitmap *src,
137 gboolean succeeded = FALSE;
139 /* Intended only for fast copies when format is equal! */
140 g_assert ((src->format & ~COGL_PREMULT_BIT) ==
141 (dst->format & ~COGL_PREMULT_BIT));
143 bpp = _cogl_pixel_format_get_bytes_per_pixel (src->format);
145 if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0)))
147 if ((dstdata = _cogl_bitmap_map (dst, COGL_BUFFER_ACCESS_WRITE, 0)))
149 srcdata += src_y * src->rowstride + src_x * bpp;
150 dstdata += dst_y * dst->rowstride + dst_x * bpp;
152 for (line=0; line<height; ++line)
154 memcpy (dstdata, srcdata, width * bpp);
155 srcdata += src->rowstride;
156 dstdata += dst->rowstride;
161 _cogl_bitmap_unmap (dst);
164 _cogl_bitmap_unmap (src);
171 cogl_bitmap_get_size_from_file (const char *filename,
175 return _cogl_bitmap_get_size_from_file (filename, width, height);
179 cogl_bitmap_new_for_data (CoglContext *context,
182 CoglPixelFormat format,
188 g_return_val_if_fail (cogl_is_context (context), NULL);
190 bmp = g_slice_new (CoglBitmap);
191 bmp->format = format;
193 bmp->height = height;
194 bmp->rowstride = rowstride;
198 bmp->shared_bmp = NULL;
201 return _cogl_bitmap_object_new (bmp);
205 _cogl_bitmap_new_with_malloc_buffer (CoglContext *context,
208 CoglPixelFormat format)
210 static CoglUserDataKey bitmap_free_key;
211 int bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
212 int rowstride = ((width * bpp) + 3) & ~3;
213 guint8 *data = g_malloc (rowstride * height);
216 bitmap = cogl_bitmap_new_for_data (context,
221 cogl_object_set_user_data (COGL_OBJECT (bitmap),
230 _cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
231 CoglPixelFormat format,
238 _COGL_GET_CONTEXT (ctx, NULL);
240 bmp = cogl_bitmap_new_for_data (ctx,
246 bmp->shared_bmp = cogl_object_ref (shared_bmp);
252 cogl_bitmap_new_from_file (const char *filename,
255 _COGL_RETURN_VAL_IF_FAIL (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
257 return _cogl_bitmap_from_file (filename, error);
261 cogl_bitmap_new_from_buffer (CoglBuffer *buffer,
262 CoglPixelFormat format,
270 _COGL_RETURN_VAL_IF_FAIL (cogl_is_buffer (buffer), NULL);
272 bmp = cogl_bitmap_new_for_data (buffer->context,
278 bmp->buffer = cogl_object_ref (buffer);
279 bmp->data = GINT_TO_POINTER (offset);
285 cogl_bitmap_new_with_size (CoglContext *context,
288 CoglPixelFormat format)
290 CoglPixelBuffer *pixel_buffer;
292 unsigned int rowstride;
294 /* creating a buffer to store "any" format does not make sense */
295 if (G_UNLIKELY (format == COGL_PIXEL_FORMAT_ANY))
298 /* for now we fallback to cogl_pixel_buffer_new, later, we could ask
299 * libdrm a tiled buffer for instance */
300 rowstride = width * _cogl_pixel_format_get_bytes_per_pixel (format);
302 pixel_buffer = cogl_pixel_buffer_new (context, height * rowstride, NULL);
304 if (G_UNLIKELY (pixel_buffer == NULL))
307 bitmap = cogl_bitmap_new_from_buffer (COGL_BUFFER (pixel_buffer),
313 cogl_object_unref (pixel_buffer);
319 cogl_bitmap_get_format (CoglBitmap *bitmap)
321 return bitmap->format;
325 _cogl_bitmap_set_format (CoglBitmap *bitmap,
326 CoglPixelFormat format)
328 bitmap->format = format;
332 cogl_bitmap_get_width (CoglBitmap *bitmap)
334 return bitmap->width;
338 cogl_bitmap_get_height (CoglBitmap *bitmap)
340 return bitmap->height;
344 cogl_bitmap_get_rowstride (CoglBitmap *bitmap)
346 return bitmap->rowstride;
350 cogl_bitmap_get_buffer (CoglBitmap *bitmap)
352 while (bitmap->shared_bmp)
353 bitmap = bitmap->shared_bmp;
355 return COGL_PIXEL_BUFFER (bitmap->buffer);
359 cogl_bitmap_error_quark (void)
361 return g_quark_from_static_string ("cogl-bitmap-error-quark");
365 _cogl_bitmap_map (CoglBitmap *bitmap,
366 CoglBufferAccess access,
367 CoglBufferMapHint hints)
369 /* Divert to another bitmap if this data is shared */
370 if (bitmap->shared_bmp)
371 return _cogl_bitmap_map (bitmap->shared_bmp, access, hints);
373 g_assert (!bitmap->mapped);
377 guint8 *data = cogl_buffer_map (bitmap->buffer,
381 COGL_NOTE (BITMAP, "A pixel array is being mapped from a bitmap. This "
382 "usually means that some conversion on the pixel array is "
383 "needed so a sub-optimal format is being used.");
387 bitmap->mapped = TRUE;
389 return data + GPOINTER_TO_INT (bitmap->data);
396 bitmap->mapped = TRUE;
403 _cogl_bitmap_unmap (CoglBitmap *bitmap)
405 /* Divert to another bitmap if this data is shared */
406 if (bitmap->shared_bmp)
408 _cogl_bitmap_unmap (bitmap->shared_bmp);
412 g_assert (bitmap->mapped);
413 bitmap->mapped = FALSE;
416 cogl_buffer_unmap (bitmap->buffer);
420 _cogl_bitmap_bind (CoglBitmap *bitmap,
421 CoglBufferAccess access,
422 CoglBufferMapHint hints)
426 /* Divert to another bitmap if this data is shared */
427 if (bitmap->shared_bmp)
428 return _cogl_bitmap_bind (bitmap->shared_bmp, access, hints);
430 g_assert (!bitmap->bound);
432 /* If the bitmap wasn't created from a buffer then the
433 implementation of bind is the same as map */
434 if (bitmap->buffer == NULL)
436 guint8 *data = _cogl_bitmap_map (bitmap, access, hints);
438 bitmap->bound = TRUE;
442 bitmap->bound = TRUE;
444 if (access == COGL_BUFFER_ACCESS_READ)
445 ptr = _cogl_buffer_bind (bitmap->buffer,
446 COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
447 else if (access == COGL_BUFFER_ACCESS_WRITE)
448 ptr = _cogl_buffer_bind (bitmap->buffer,
449 COGL_BUFFER_BIND_TARGET_PIXEL_PACK);
451 g_assert_not_reached ();
453 /* The data pointer actually stores the offset */
454 return GPOINTER_TO_INT (bitmap->data) + ptr;
458 _cogl_bitmap_unbind (CoglBitmap *bitmap)
460 /* Divert to another bitmap if this data is shared */
461 if (bitmap->shared_bmp)
463 _cogl_bitmap_unbind (bitmap->shared_bmp);
467 g_assert (bitmap->bound);
468 bitmap->bound = FALSE;
470 /* If the bitmap wasn't created from a pixel array then the
471 implementation of unbind is the same as unmap */
473 _cogl_buffer_unbind (bitmap->buffer);
475 _cogl_bitmap_unmap (bitmap);