aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/gfx/gfx_resource.c
diff options
context:
space:
mode:
authorJordi Vilalta Prat2009-02-15 06:10:59 +0000
committerJordi Vilalta Prat2009-02-15 06:10:59 +0000
commitfa6e10e9cec163845aa29e7940c86e9c9ab8a2bc (patch)
treece87338830cc8c149e1de545246bcefe4f45da00 /engines/sci/gfx/gfx_resource.c
parent7c148ddf021c990fa866b7600f979aac9a5b26c9 (diff)
downloadscummvm-rg350-fa6e10e9cec163845aa29e7940c86e9c9ab8a2bc.tar.gz
scummvm-rg350-fa6e10e9cec163845aa29e7940c86e9c9ab8a2bc.tar.bz2
scummvm-rg350-fa6e10e9cec163845aa29e7940c86e9c9ab8a2bc.zip
Import the SCI engine sources from the FreeSCI Glutton branch (it doesn't compile yet)
svn-id: r38192
Diffstat (limited to 'engines/sci/gfx/gfx_resource.c')
-rw-r--r--engines/sci/gfx/gfx_resource.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/engines/sci/gfx/gfx_resource.c b/engines/sci/gfx/gfx_resource.c
new file mode 100644
index 0000000000..6ac7567d76
--- /dev/null
+++ b/engines/sci/gfx/gfx_resource.c
@@ -0,0 +1,434 @@
+/***************************************************************************
+ gfx_resource.c Copyright (C) 2000 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+
+#include <gfx_system.h>
+#include <gfx_resource.h>
+#include <gfx_tools.h>
+
+gfx_mode_t mode_1x1_color_index = { /* Fake 1x1 mode */
+ /* xfact */ 1, /* yfact */ 1,
+ /* bytespp */ 1,
+ /* flags */ 0,
+ /* palette */ NULL,
+
+ /* color masks */ 0, 0, 0, 0,
+ /* color shifts */ 0, 0, 0, 0
+};
+
+
+static void
+gfxr_free_loop(gfx_driver_t *driver, gfxr_loop_t *loop)
+{
+ int i;
+
+ if (loop->cels) {
+ for (i = 0; i < loop->cels_nr; i++)
+ if (loop->cels[i])
+ gfx_free_pixmap(driver, loop->cels[i]);
+
+ free(loop->cels);
+ }
+}
+
+void
+gfxr_free_view(gfx_driver_t *driver, gfxr_view_t *view)
+{
+ int i;
+
+ if (view->colors && !(view->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE))
+ free(view->colors);
+
+ if (view->loops) {
+ for (i = 0; i < view->loops_nr; i++)
+ gfxr_free_loop(driver, view->loops + i);
+
+ free(view->loops);
+ }
+ free(view);
+}
+
+
+static void
+pixmap_endianness_reverse_2_simple(byte *data, int area)
+{
+ int c;
+ for (c = 0; c < area; c++) {
+ byte val = *data;
+ *data = data[1];
+ data[1] = val;
+
+ data += 2;
+ }
+}
+
+static void
+pixmap_endianness_reverse_2(byte *data, int area)
+{
+ int c;
+ int sl = sizeof(unsigned long);
+
+ for (c = 0; c < (area & ~(sl-1)); c += (sl>>1)) {
+ unsigned long temp;
+
+ memcpy(&temp, data, sl);
+
+ /* The next line will give warnings on 32 bit archs, but
+ ** that's OK. */
+#if SIZEOF_LONG < 8
+ temp = 0;
+#else
+ temp = ((temp & 0xff00ff00ff00ff00l) >> 8)
+ | ((temp & 0x00ff00ff00ff00ffl) << 8);
+#endif /* SIZEOF_INT < 8 */
+
+ memcpy(data, &temp, sl);
+
+ data += sl;
+ }
+
+ pixmap_endianness_reverse_2_simple(data, area & (sl-1));
+}
+
+static void
+pixmap_endianness_reverse_3_simple(byte *data, int area)
+{
+ int c;
+ for (c = 0; c < area; c++) {
+ byte val0 = data[0];
+
+ data[0] = data[2];
+ data[2] = val0;
+
+ data += 3;
+ }
+}
+
+static void
+pixmap_endianness_reverse_4_simple(byte *data, int area)
+{
+ int c;
+ for (c = 0; c < area; c++) {
+ byte val0 = data[0];
+ byte val1 = data[1];
+
+ data[0] = data[3];
+ data[3] = val0;
+
+ data[1] = data[2];
+ data[2] = val1;
+
+ data += 4;
+ }
+}
+
+static void
+pixmap_endianness_reverse_4(byte *data, int area)
+{
+ int c;
+ int sl = sizeof(unsigned long);
+
+ for (c = 0; c < (area & ~(sl-1)); c += (sl>>2)) {
+ unsigned long temp;
+
+ memcpy(&temp, data, sl);
+
+ /* The next lines will give warnings on 32 bit archs, but
+ ** that's OK. */
+#if SIZEOF_LONG < 8
+ temp = 0l;
+#else
+ temp = ((temp & 0xffff0000ffff0000l) >> 16)
+ | ((temp & 0x0000ffff0000ffffl) << 16);
+ temp = ((temp & 0xff00ff00ff00ff00l) >> 8)
+ | ((temp & 0x00ff00ff00ff00ffl) << 8);
+#endif /* SIZEOF_LONG < 8 */
+
+ memcpy(data, &temp, sl);
+
+ data += sl;
+ }
+
+ pixmap_endianness_reverse_4_simple(data, area & (sl-1));
+}
+
+gfx_pixmap_t *
+gfxr_endianness_adjust(gfx_pixmap_t *pixmap, gfx_mode_t *mode)
+{
+ int bytespp;
+ byte *data;
+
+ if (!pixmap || !pixmap->data || !mode) {
+ GFXERROR("gfxr_endianness_adjust(): Invoked with invalid values\n");
+ BREAKPOINT();
+ return NULL;
+ }
+
+ if (!(mode->flags & GFX_MODE_FLAG_REVERSE_ENDIAN))
+ return pixmap;
+
+ bytespp = mode->bytespp;
+
+ data = pixmap->data;
+
+ switch (bytespp) {
+ case 1:
+ break;
+
+ case 2: pixmap_endianness_reverse_2(data, pixmap->xl
+ * pixmap->yl);
+ break;
+
+ case 3: pixmap_endianness_reverse_3_simple(data, pixmap->xl
+ * pixmap->yl);
+ break;
+
+ case 4: pixmap_endianness_reverse_4(data, pixmap->xl * pixmap->yl);
+ break;
+
+ default: fprintf(stderr,"gfxr_endianness_adjust(): Cannot adjust endianness for %d bytespp!\n", bytespp);
+ return NULL;
+ }
+
+ return pixmap;
+}
+
+
+/* Now construct the pixmap scaling functions */
+#define EXTRA_BYTE_OFFSET 0
+#define SIZETYPE guint8
+#define FUNCNAME _gfx_xlate_pixmap_unfiltered_1
+#define FUNCNAME_LINEAR _gfx_xlate_pixmap_linear_1
+#define FUNCNAME_TRILINEAR _gfx_xlate_pixmap_trilinear_1
+#define COPY_BYTES 1
+#include "gfx_pixmap_scale.c"
+#undef COPY_BYTES
+
+#define SIZETYPE guint16
+#define FUNCNAME _gfx_xlate_pixmap_unfiltered_2
+#define FUNCNAME_LINEAR _gfx_xlate_pixmap_linear_2
+#define FUNCNAME_TRILINEAR _gfx_xlate_pixmap_trilinear_2
+#define COPY_BYTES 2
+#include "gfx_pixmap_scale.c"
+#undef COPY_BYTES
+
+#ifdef WORDS_BIGENDIAN
+# undef EXTRA_BYTE_OFFSET
+# define EXTRA_BYTE_OFFSET 1
+#endif /* WORDS_BIGENDIAN */
+#define SIZETYPE guint32
+#define FUNCNAME _gfx_xlate_pixmap_unfiltered_3
+#define FUNCNAME_LINEAR _gfx_xlate_pixmap_linear_3
+#define FUNCNAME_TRILINEAR _gfx_xlate_pixmap_trilinear_3
+#define COPY_BYTES 3
+#include "gfx_pixmap_scale.c"
+#undef COPY_BYTES
+#ifdef WORDS_BIGENDIAN
+# undef EXTRA_BYTE_OFFSET
+# define EXTRA_BYTE_OFFSET 0
+#endif /* WORDS_BIGENDIAN */
+
+#define SIZETYPE guint32
+#define FUNCNAME _gfx_xlate_pixmap_unfiltered_4
+#define FUNCNAME_LINEAR _gfx_xlate_pixmap_linear_4
+#define FUNCNAME_TRILINEAR _gfx_xlate_pixmap_trilinear_4
+#define COPY_BYTES 4
+#include "gfx_pixmap_scale.c"
+#undef COPY_BYTES
+#undef EXTRA_BYTE_OFFSET
+#undef SIZETYPE
+
+static inline void
+_gfx_xlate_pixmap_unfiltered(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale)
+{
+ switch (mode->bytespp) {
+
+ case 1:_gfx_xlate_pixmap_unfiltered_1(mode, pxm, scale);
+ break;
+
+ case 2:_gfx_xlate_pixmap_unfiltered_2(mode, pxm, scale);
+ break;
+
+ case 3:_gfx_xlate_pixmap_unfiltered_3(mode, pxm, scale);
+ break;
+
+ case 4:_gfx_xlate_pixmap_unfiltered_4(mode, pxm, scale);
+ break;
+
+ default:
+ GFXERROR("Invalid mode->bytespp=%d\n", mode->bytespp);
+
+ }
+
+ if (pxm->flags & GFX_PIXMAP_FLAG_SCALED_INDEX) {
+ pxm->xl = pxm->index_xl;
+ pxm->yl = pxm->index_yl;
+ } else {
+ pxm->xl = pxm->index_xl * mode->xfact;
+ pxm->yl = pxm->index_yl * mode->yfact;
+ }
+}
+
+static inline void
+_gfx_xlate_pixmap_linear(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale)
+{
+ if (mode->palette || !scale) { /* fall back to unfiltered */
+ _gfx_xlate_pixmap_unfiltered(mode, pxm, scale);
+ return;
+ }
+
+ pxm->xl = pxm->index_xl * mode->xfact;
+ pxm->yl = pxm->index_yl * mode->yfact;
+
+ switch (mode->bytespp) {
+
+ case 1:_gfx_xlate_pixmap_linear_1(mode, pxm, scale);
+ break;
+
+ case 2:_gfx_xlate_pixmap_linear_2(mode, pxm, scale);
+ break;
+
+ case 3:_gfx_xlate_pixmap_linear_3(mode, pxm, scale);
+ break;
+
+ case 4:_gfx_xlate_pixmap_linear_4(mode, pxm, scale);
+ break;
+
+ default:
+ GFXERROR("Invalid mode->bytespp=%d\n", mode->bytespp);
+
+ }
+
+}
+
+static inline void
+_gfx_xlate_pixmap_trilinear(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale)
+{
+ if (mode->palette || !scale) { /* fall back to unfiltered */
+ _gfx_xlate_pixmap_unfiltered(mode, pxm, scale);
+ return;
+ }
+
+ pxm->xl = pxm->index_xl * mode->xfact;
+ pxm->yl = pxm->index_yl * mode->yfact;
+
+ switch (mode->bytespp) {
+
+ case 1:_gfx_xlate_pixmap_trilinear_1(mode, pxm, scale);
+ break;
+
+ case 2:_gfx_xlate_pixmap_trilinear_2(mode, pxm, scale);
+ break;
+
+ case 3:_gfx_xlate_pixmap_trilinear_3(mode, pxm, scale);
+ break;
+
+ case 4:_gfx_xlate_pixmap_trilinear_4(mode, pxm, scale);
+ break;
+
+ default:
+ GFXERROR("Invalid mode->bytespp=%d\n", mode->bytespp);
+
+ }
+
+}
+
+void
+gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t filter)
+{
+ int was_allocated = 0;
+
+ if (mode->palette
+ && !(pxm->flags & GFX_PIXMAP_FLAG_PALETTE_ALLOCATED)) {
+ int i;
+
+ for (i = 0; i < pxm->colors_nr; i++) {
+ if (gfx_alloc_color(mode->palette, pxm->colors + i) < 0) {
+ GFXWARN("Failed to allocate color %d/%d in pixmap (color %02x/%02x/%02x)!\n",
+ i, pxm->colors_nr, pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b);
+ pxm->colors[i].global_index = 0;
+ }
+ /*
+ GFXDEBUG("alloc(%02x/%02x/%02x) -> %d\n", pxm->colors[i].r,pxm->colors[i].g,pxm->colors[i].b,pxm->colors[i].global_index);
+ */
+ }
+
+ pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_ALLOCATED;
+ }
+
+
+ if (!pxm->data) {
+ pxm->data = (byte*)sci_malloc(mode->xfact * mode->yfact * pxm->index_xl * pxm->index_yl * mode->bytespp + 1);
+ /* +1: Eases coying on BE machines in 24 bpp packed mode */
+ /* Assume that memory, if allocated already, will be sufficient */
+
+ /* Allocate alpha map */
+ if (!mode->alpha_mask && pxm->colors_nr < GFX_PIC_COLORS)
+ pxm->alpha_map = (byte*)sci_malloc(mode->xfact * mode->yfact * pxm->index_xl * pxm->index_yl + 1);
+ } else
+ was_allocated = 1;
+
+ switch (filter) {
+
+ case GFX_XLATE_FILTER_NONE: _gfx_xlate_pixmap_unfiltered(mode, pxm, !(pxm->flags & GFX_PIXMAP_FLAG_SCALED_INDEX));
+ break;
+
+ case GFX_XLATE_FILTER_LINEAR: _gfx_xlate_pixmap_linear(mode, pxm, !(pxm->flags & GFX_PIXMAP_FLAG_SCALED_INDEX));
+ break;
+
+ case GFX_XLATE_FILTER_TRILINEAR: _gfx_xlate_pixmap_trilinear(mode, pxm, !(pxm->flags & GFX_PIXMAP_FLAG_SCALED_INDEX));
+ break;
+
+ default:
+ GFXERROR("Attempt to filter pixmap %04x in invalid mode #%d\n", pxm->ID, filter);
+
+ if (!was_allocated) {
+ if (!mode->alpha_mask && pxm->colors_nr < GFX_PIC_COLORS)
+ free(pxm->alpha_map);
+ free(pxm->data);
+ }
+ }
+}
+
+
+void
+gfxr_free_pic(gfx_driver_t *driver, gfxr_pic_t *pic)
+{
+ gfx_free_pixmap(driver, pic->visual_map);
+ gfx_free_pixmap(driver, pic->priority_map);
+ gfx_free_pixmap(driver, pic->control_map);
+ pic->visual_map = NULL;
+ pic->priority_map = NULL;
+ pic->control_map = NULL;
+ if (pic->internal)
+ free(pic->internal);
+ pic->internal = NULL;
+ if (pic->undithered_buffer)
+ free(pic->undithered_buffer);
+ pic->undithered_buffer = 0;
+ free(pic);
+}
+