os/graphics/m3g/m3gcore11/src/m3g_background.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/m3g/m3gcore11/src/m3g_background.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,676 @@
     1.4 +/*
     1.5 +* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: Background implementation
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +/*!
    1.23 + * \internal
    1.24 + * \file
    1.25 + * \brief Background implementation
    1.26 + */
    1.27 +
    1.28 +#ifndef M3G_CORE_INCLUDE
    1.29 +#   error included by m3g_core.c; do not compile separately.
    1.30 +#endif
    1.31 +
    1.32 +#include "m3g_background.h"
    1.33 +#include "m3g_image.h"
    1.34 +#include "m3g_memory.h"
    1.35 +#include "m3g_animationtrack.h"
    1.36 +#include "m3g_rendercontext.h"
    1.37 +
    1.38 +/*----------------------------------------------------------------------
    1.39 + * Internal functions
    1.40 + *--------------------------------------------------------------------*/
    1.41 +
    1.42 +/*!
    1.43 + * \internal
    1.44 + * \brief Destroys this Background object.
    1.45 + *
    1.46 + * \param obj Background object
    1.47 + */
    1.48 +static void m3gDestroyBackground(Object *obj)
    1.49 +{
    1.50 +    Background *background = (Background *) obj;
    1.51 +    M3G_VALIDATE_OBJECT(background);
    1.52 +
    1.53 +    M3G_ASSIGN_REF(background->image, NULL);
    1.54 +    m3gDestroyObject(obj);
    1.55 +}
    1.56 +
    1.57 +/*!
    1.58 + * \internal
    1.59 + * \brief Applies background color and image
    1.60 + * using a textured quad.
    1.61 + *
    1.62 + * \param ctx           render context
    1.63 + * \param background    Background object
    1.64 + */
    1.65 +static void m3gApplyBackground(RenderContext *ctx, Background *background)
    1.66 +{
    1.67 +    GLbitfield glBits = 0;
    1.68 +    GLfixed temp[4];
    1.69 +    
    1.70 +    if (background->depthClearEnable) {
    1.71 +        glBits |= GL_DEPTH_BUFFER_BIT;
    1.72 +    }
    1.73 +
    1.74 +    /* Skip color buffer clearing if the background image
    1.75 +     * fills the whole viewport. This is guaranteed to happen
    1.76 +     * if the crop rectangle is non-zero and both X and Y
    1.77 +     * wrapping modes are REPEAT. */
    1.78 +    
    1.79 +    if (background->colorClearEnable) {
    1.80 +        if (background->image == NULL ||
    1.81 +            background->crop.width == 0 ||
    1.82 +            background->crop.height == 0 ||
    1.83 +            background->modeX == M3G_BORDER ||
    1.84 +            background->modeY == M3G_BORDER)
    1.85 +        {
    1.86 +            glBits |= GL_COLOR_BUFFER_BIT;
    1.87 +            m3gGLColor(background->color, temp);
    1.88 +            glClearColorx(temp[0], temp[1], temp[2], temp[3]);
    1.89 +        }
    1.90 +    }
    1.91 +    
    1.92 +    /* Clear color and/or depth buffer (or neither) */
    1.93 +    glClear(glBits);
    1.94 +
    1.95 +    /* Apply background image using a quad that
    1.96 +       fills the viewport */
    1.97 +
    1.98 +    if (background->colorClearEnable &&
    1.99 +        background->image != NULL &&
   1.100 +        background->crop.width != 0 && 
   1.101 +        background->crop.height != 0)
   1.102 +    {
   1.103 +        {
   1.104 +            /* Texture coordinates */
   1.105 +            M3Gshort texvert[4 * 2];
   1.106 +            /* Quad that fills the viewport */
   1.107 +            M3Gint vert[4 * 3]   = { -65536,  65536, 0,
   1.108 +                                     -65536, -65536, 0,
   1.109 +                                      65536,  65536, 0,
   1.110 +                                      65536, -65536, 0 };
   1.111 +            Rect rImage, rIntersection;
   1.112 +            M3Gbool intersects;
   1.113 +            Image *imagePow2;
   1.114 +
   1.115 +            /* Get power of two image */
   1.116 +            imagePow2 = m3gGetPowerOfTwoImage(background->image);
   1.117 +            /* If NULL -> out of memory */
   1.118 +            if (!imagePow2) {
   1.119 +                return;
   1.120 +            }
   1.121 +
   1.122 +            rImage.x = 0;
   1.123 +            rImage.y = 0;
   1.124 +            rImage.width = m3gGetWidth(background->image);
   1.125 +            rImage.height = m3gGetHeight(background->image);
   1.126 +
   1.127 +            /* Intersection of source image and crop rectangle */
   1.128 +            intersects = m3gIntersectRectangle(&rIntersection, &rImage, &background->crop);
   1.129 +
   1.130 +            /* Setup X vertices and texture S coordinates */
   1.131 +            if (background->modeX == M3G_BORDER) {
   1.132 +                /* If both modes are border and no intersection ->
   1.133 +                   nothing to draw */
   1.134 +                if (background->modeY == M3G_BORDER && !intersects) {
   1.135 +                    return;
   1.136 +                }
   1.137 +
   1.138 +                texvert[0 * 2 + 0] = (M3Gshort) rIntersection.x;
   1.139 +                texvert[1 * 2 + 0] = (M3Gshort) rIntersection.x;
   1.140 +                texvert[2 * 2 + 0] = (M3Gshort) (rIntersection.x + rIntersection.width);
   1.141 +                texvert[3 * 2 + 0] = (M3Gshort) (rIntersection.x + rIntersection.width);
   1.142 +
   1.143 +                vert[0 * 3 + 0] = -65536 + 2 * 65536 * (rIntersection.x - background->crop.x) / background->crop.width;
   1.144 +                vert[1 * 3 + 0] = vert[0 * 3 + 0];
   1.145 +                vert[2 * 3 + 0] = vert[0 * 3 + 0] + 2 * 65536 * rIntersection.width / background->crop.width;
   1.146 +                vert[3 * 3 + 0] = vert[2 * 3 + 0];
   1.147 +            }
   1.148 +            else {
   1.149 +                /* In repeat mode texture coordinates are directly crop rectangle coordinates */
   1.150 +                texvert[0 * 2 + 0] = (M3Gshort) background->crop.x;
   1.151 +                texvert[1 * 2 + 0] = (M3Gshort) background->crop.x;
   1.152 +                texvert[2 * 2 + 0] = (M3Gshort) (background->crop.x + background->crop.width);
   1.153 +                texvert[3 * 2 + 0] = (M3Gshort) (background->crop.x + background->crop.width);
   1.154 +            }
   1.155 +
   1.156 +            /* Setup Y vertices and texture T coordinates */
   1.157 +            if (background->modeY == M3G_BORDER) {
   1.158 +                texvert[0 * 2 + 1] = (M3Gshort) rIntersection.y;
   1.159 +                texvert[1 * 2 + 1] = (M3Gshort) (rIntersection.y + rIntersection.height);
   1.160 +                texvert[2 * 2 + 1] = (M3Gshort) rIntersection.y;
   1.161 +                texvert[3 * 2 + 1] = (M3Gshort) (rIntersection.y + rIntersection.height);
   1.162 +
   1.163 +
   1.164 +                vert[0 * 3 + 1] =  65536 - 2 * 65536 * (rIntersection.y - background->crop.y) / background->crop.height;
   1.165 +                vert[1 * 3 + 1] = vert[0 * 3 + 1] - 2 * 65536 * rIntersection.height / background->crop.height;
   1.166 +                vert[2 * 3 + 1] = vert[0 * 3 + 1];
   1.167 +                vert[3 * 3 + 1] = vert[1 * 3 + 1];
   1.168 +            }
   1.169 +            else {
   1.170 +                /* In repeat mode texture coordinates are directly crop rectangle coordinates */
   1.171 +                texvert[0 * 2 + 1] = (M3Gshort) background->crop.y;
   1.172 +                texvert[1 * 2 + 1] = (M3Gshort) (background->crop.y + background->crop.height);
   1.173 +                texvert[2 * 2 + 1] = (M3Gshort) background->crop.y;
   1.174 +                texvert[3 * 2 + 1] = (M3Gshort) (background->crop.y + background->crop.height);
   1.175 +            }
   1.176 +
   1.177 +            /* Disable unwanted state and depth writes */
   1.178 +            m3gApplyAppearance(NULL, ctx, 0);
   1.179 +            glDepthMask(GL_FALSE);
   1.180 +
   1.181 +            /* Disable color array, normals and textures*/
   1.182 +            glDisableClientState(GL_COLOR_ARRAY);
   1.183 +            glDisableClientState(GL_NORMAL_ARRAY);
   1.184 +        
   1.185 +            /* Background image to texture unit 0 */
   1.186 +            glClientActiveTexture(GL_TEXTURE0);
   1.187 +            glActiveTexture(GL_TEXTURE0);
   1.188 +            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   1.189 +            glTexCoordPointer(2, GL_SHORT, 0, texvert);
   1.190 +            glEnable(GL_TEXTURE_2D);
   1.191 +            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLfixed) GL_REPLACE);
   1.192 +            m3gBindTextureImage(imagePow2,
   1.193 +                                M3G_FILTER_BASE_LEVEL,
   1.194 +                                m3gIsAccelerated(ctx) ? M3G_FILTER_LINEAR : M3G_FILTER_NEAREST);
   1.195 +
   1.196 +            /* Set wrapping */
   1.197 +            if (background->modeX == M3G_REPEAT) {
   1.198 +                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   1.199 +            }
   1.200 +            else {
   1.201 +                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1.202 +            }
   1.203 +    
   1.204 +            if (background->modeY == M3G_REPEAT) {
   1.205 +                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   1.206 +            }
   1.207 +            else {
   1.208 +                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1.209 +            }
   1.210 +
   1.211 +            /* Texture matrix scale */
   1.212 +            glMatrixMode(GL_TEXTURE);
   1.213 +            glLoadIdentity();
   1.214 +            glScalef(   m3gRcp((M3Gfloat)m3gGetWidth(background->image)),
   1.215 +                        m3gRcp((M3Gfloat)m3gGetHeight(background->image)),
   1.216 +                        1.f);
   1.217 +            glMatrixMode(GL_MODELVIEW);
   1.218 +
   1.219 +            /* Load vertices */
   1.220 +            glEnableClientState(GL_VERTEX_ARRAY);
   1.221 +            glVertexPointer(3, GL_FIXED, 0, vert);
   1.222 +        
   1.223 +            /* Set up an identity modelview and projection */
   1.224 +            m3gPushScreenSpace(ctx, M3G_FALSE);
   1.225 +
   1.226 +            /* Load indices -> draws the background */
   1.227 +            M3G_BEGIN_PROFILE(M3G_INTERFACE(ctx), M3G_PROFILE_NGL_DRAW);
   1.228 +            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   1.229 +            M3G_END_PROFILE(M3G_INTERFACE(ctx), M3G_PROFILE_NGL_DRAW);
   1.230 +        
   1.231 +            m3gPopSpace(ctx);
   1.232 +            m3gReleaseTextureImage(imagePow2);
   1.233 +        }
   1.234 +    }
   1.235 +}
   1.236 +
   1.237 +/*!
   1.238 + * \internal
   1.239 + * \brief Overloaded Object3D method.
   1.240 + *
   1.241 + * \param property      animation property
   1.242 + * \retval M3G_TRUE     property supported
   1.243 + * \retval M3G_FALSE    property not supported
   1.244 + */
   1.245 +static M3Gbool m3gBackgroundIsCompatible(M3Gint property)
   1.246 +{
   1.247 +    switch (property) {
   1.248 +    case M3G_ANIM_ALPHA:
   1.249 +    case M3G_ANIM_COLOR:
   1.250 +    case M3G_ANIM_CROP:
   1.251 +        return M3G_TRUE;
   1.252 +    default:
   1.253 +        return m3gObjectIsCompatible(property);
   1.254 +    }
   1.255 +}
   1.256 +
   1.257 +/*!
   1.258 + * \internal
   1.259 + * \brief Overloaded Object3D method.
   1.260 + *
   1.261 + * \param self          Background object
   1.262 + * \param property      animation property
   1.263 + * \param valueSize     size of value array
   1.264 + * \param value         value array
   1.265 + */
   1.266 +static void m3gBackgroundUpdateProperty(Object *self,
   1.267 +                                        M3Gint property,
   1.268 +                                        M3Gint valueSize,
   1.269 +                                        const M3Gfloat *value)
   1.270 +{
   1.271 +    Background *background = (Background *)self;
   1.272 +    M3G_VALIDATE_OBJECT(background);
   1.273 +    M3G_ASSERT_PTR(value);
   1.274 +    
   1.275 +    switch (property) {
   1.276 +    case M3G_ANIM_ALPHA:
   1.277 +        M3G_ASSERT(valueSize >= 1);
   1.278 +        background->color = m3gAlpha1f(value[0])
   1.279 +            & (background->color | M3G_ALPHA_MASK);
   1.280 +        break;
   1.281 +    case M3G_ANIM_COLOR:
   1.282 +        M3G_ASSERT(valueSize >= 3);
   1.283 +        background->color = m3gColor3f(value[0], value[1], value[2])
   1.284 +            & (background->color | M3G_RGB_MASK);
   1.285 +        break;
   1.286 +    case M3G_ANIM_CROP:
   1.287 +        M3G_ASSERT(valueSize >= 2);
   1.288 +        background->crop.x = m3gRoundToInt(value[0]);
   1.289 +        background->crop.y = m3gRoundToInt(value[1]);
   1.290 +        if (valueSize > 2) {
   1.291 +            M3G_ASSERT(valueSize >= 4);
   1.292 +            background->crop.width =
   1.293 +                (value[2] < 0) ? 0 : m3gRoundToInt(value[2]);
   1.294 +            background->crop.height =
   1.295 +                (value[3] < 0) ? 0 : m3gRoundToInt(value[3]);
   1.296 +        }
   1.297 +        break;
   1.298 +    default:
   1.299 +        m3gObjectUpdateProperty(self, property, valueSize, value);
   1.300 +    }
   1.301 +}
   1.302 +
   1.303 +/*!
   1.304 + * \internal
   1.305 + * \brief Overloaded Object3D method.
   1.306 + *
   1.307 + * \param self Background object
   1.308 + * \param references array of reference objects
   1.309 + * \return number of references
   1.310 + */
   1.311 +static M3Gint m3gBackgroundDoGetReferences(Object *self, Object **references)
   1.312 +{
   1.313 +    Background *bg = (Background *)self;
   1.314 +    M3Gint num = m3gObjectDoGetReferences(self, references);
   1.315 +    if (bg->image != NULL) {
   1.316 +        if (references != NULL)
   1.317 +            references[num] = (Object *)bg->image;
   1.318 +        num++;
   1.319 +    }
   1.320 +    return num;
   1.321 +}
   1.322 +
   1.323 +/*!
   1.324 + * \internal
   1.325 + * \brief Overloaded Object3D method.
   1.326 + */
   1.327 +static Object *m3gBackgroundFindID(Object *self, M3Gint userID)
   1.328 +{
   1.329 +    Background *bg = (Background *)self;
   1.330 +    Object *found = m3gObjectFindID(self, userID);
   1.331 +
   1.332 +    if (!found && bg->image) {
   1.333 +        found = m3gFindID((Object*) bg->image, userID);
   1.334 +    }
   1.335 +    return found;
   1.336 +}
   1.337 +
   1.338 +/*!
   1.339 + * \internal
   1.340 + * \brief Overloaded Object3D method.
   1.341 + *
   1.342 + * \param originalObj original Background object
   1.343 + * \param cloneObj pointer to cloned Background object
   1.344 + * \param pairs array for all object-duplicate pairs
   1.345 + * \param numPairs number of pairs
   1.346 + */
   1.347 +static M3Gbool m3gBackgroundDuplicate(const Object *originalObj,
   1.348 +                                      Object **cloneObj,
   1.349 +                                      Object **pairs,
   1.350 +                                      M3Gint *numPairs)
   1.351 +{
   1.352 +    Background *original = (Background *)originalObj;
   1.353 +    Background *clone = (Background *)m3gCreateBackground(originalObj->interface);
   1.354 +    *cloneObj = (Object *)clone;
   1.355 +    if (*cloneObj == NULL) {
   1.356 +        return M3G_FALSE;
   1.357 +    }
   1.358 +
   1.359 +    if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
   1.360 +        clone->color = original->color;
   1.361 +        clone->modeX = original->modeX;
   1.362 +        clone->modeY = original->modeY;
   1.363 +        clone->crop = original->crop;
   1.364 +        clone->colorClearEnable = original->colorClearEnable;
   1.365 +        clone->depthClearEnable = original->depthClearEnable;
   1.366 +        M3G_ASSIGN_REF(clone->image, original->image);
   1.367 +        return M3G_TRUE;
   1.368 +    }
   1.369 +    else {
   1.370 +        return M3G_FALSE;
   1.371 +    }
   1.372 +}
   1.373 +
   1.374 +/*!
   1.375 + * \internal
   1.376 + * \brief Initializes a Background object. See specification
   1.377 + * for default values.
   1.378 + *
   1.379 + * \param m3g           M3G interface
   1.380 + * \param background    Background object
   1.381 + */
   1.382 +static void m3gInitBackground(Interface *m3g, Background *background)
   1.383 +{
   1.384 +    /* Background is derived from Object */
   1.385 +    m3gInitObject(&background->object, m3g, M3G_CLASS_BACKGROUND);
   1.386 +
   1.387 +    background->modeX = M3G_BORDER; 
   1.388 +    background->modeY = M3G_BORDER; 
   1.389 +    background->colorClearEnable = M3G_TRUE;
   1.390 +    background->depthClearEnable = M3G_TRUE;
   1.391 +}
   1.392 +
   1.393 +/*----------------------------------------------------------------------
   1.394 + * Virtual function table
   1.395 + *--------------------------------------------------------------------*/
   1.396 +
   1.397 +static const ObjectVFTable m3gvf_Background = {
   1.398 +    m3gObjectApplyAnimation,
   1.399 +    m3gBackgroundIsCompatible,
   1.400 +    m3gBackgroundUpdateProperty,
   1.401 +    m3gBackgroundDoGetReferences,
   1.402 +    m3gBackgroundFindID,
   1.403 +    m3gBackgroundDuplicate,
   1.404 +    m3gDestroyBackground
   1.405 +};
   1.406 +
   1.407 +
   1.408 +/*----------------------------------------------------------------------
   1.409 + * Public API functions
   1.410 + *--------------------------------------------------------------------*/
   1.411 +
   1.412 +/*!
   1.413 + * \brief Creates a Background object.
   1.414 + *
   1.415 + * \param interface     M3G interface
   1.416 + * \retval Background new Background object
   1.417 + * \retval NULL Background creating failed
   1.418 + */
   1.419 +
   1.420 +/*@access M3GInterface@*/
   1.421 +/*@access M3Gobject@*/
   1.422 +M3G_API M3GBackground m3gCreateBackground(M3GInterface interface)
   1.423 +{
   1.424 +    Interface *m3g = (Interface *) interface;
   1.425 +    M3G_VALIDATE_INTERFACE(m3g);
   1.426 +
   1.427 +    {
   1.428 +        Background *background =  m3gAllocZ(m3g, sizeof(Background));
   1.429 +    
   1.430 +        if (background != NULL) {
   1.431 +            m3gInitBackground(m3g, background);
   1.432 +        }
   1.433 +
   1.434 +        return (M3GBackground) background;
   1.435 +    }
   1.436 +}
   1.437 +
   1.438 +/*!
   1.439 + * \brief Sets background color.
   1.440 + *
   1.441 + * \param handle        Background object
   1.442 + * \param ARGB          background color as ARGB
   1.443 + */
   1.444 +
   1.445 +/*@access M3Gobject@*/
   1.446 +M3G_API void m3gSetBgColor(M3GBackground handle, M3Guint ARGB)
   1.447 +{
   1.448 +    Background *background = (Background *) handle;
   1.449 +    M3G_VALIDATE_OBJECT(background);
   1.450 +    
   1.451 +    background->color = ARGB;
   1.452 +}
   1.453 +
   1.454 +/*!
   1.455 + * \brief Sets background image x and y mode.
   1.456 + *
   1.457 + * \param handle        Background object
   1.458 + * \param modeX         Image X mode
   1.459 + * \param modeY         Image Y mode
   1.460 + */
   1.461 +
   1.462 +/*@access M3Gobject@*/
   1.463 +M3G_API void m3gSetBgMode(M3GBackground handle, M3Gint modeX, M3Gint modeY)
   1.464 +{
   1.465 +    Background *background = (Background *) handle;
   1.466 +    M3G_VALIDATE_OBJECT(background);
   1.467 +    
   1.468 +    /* Check for errors */
   1.469 +    if (modeX < M3G_BORDER || modeX > M3G_REPEAT ||
   1.470 +        modeY < M3G_BORDER || modeY > M3G_REPEAT) {
   1.471 +        m3gRaiseError(M3G_INTERFACE(background), M3G_INVALID_VALUE);
   1.472 +        return;
   1.473 +    }
   1.474 +
   1.475 +    background->modeX = modeX;
   1.476 +    background->modeY = modeY;
   1.477 +}
   1.478 +
   1.479 +/*!
   1.480 + * \brief Sets background image crop rectangle.
   1.481 + *
   1.482 + * \param handle        Background object
   1.483 + * \param cropX         crop upper left x
   1.484 + * \param cropY         crop upper left y
   1.485 + * \param width         crop width
   1.486 + * \param height        crop height
   1.487 + */
   1.488 +
   1.489 +/*@access M3Gobject@*/
   1.490 +M3G_API void m3gSetBgCrop(M3GBackground handle,
   1.491 +                          M3Gint cropX, M3Gint cropY,
   1.492 +                          M3Gint width, M3Gint height)
   1.493 +{
   1.494 +    Background *background = (Background *) handle;
   1.495 +    M3G_VALIDATE_OBJECT(background);
   1.496 +
   1.497 +    /* Check for errors */
   1.498 +    if (width < 0 || height < 0) {
   1.499 +        m3gRaiseError(M3G_INTERFACE(background), M3G_INVALID_VALUE);
   1.500 +        return;
   1.501 +    }
   1.502 +
   1.503 +    background->crop.x = cropX;
   1.504 +    background->crop.y = cropY;
   1.505 +    background->crop.width = width;
   1.506 +    background->crop.height = height;
   1.507 +}
   1.508 +
   1.509 +/*!
   1.510 + * \brief Sets background image.
   1.511 + *
   1.512 + * \param handle        Background object
   1.513 + * \param hImage        Image2D object or NULL
   1.514 + */
   1.515 +
   1.516 +/*@access M3Gobject@*/
   1.517 +M3G_API void m3gSetBgImage(M3GBackground handle, M3GImage hImage)
   1.518 +{
   1.519 +    Background *background = (Background *) handle;
   1.520 +    Image *image = (Image *)hImage;
   1.521 +    M3G_VALIDATE_OBJECT(background);
   1.522 +
   1.523 +    if (image != NULL) {
   1.524 +        /* Check allowed formats */
   1.525 +        if (m3gGetFormat(image) != M3G_RGB &&
   1.526 +            m3gGetFormat(image) != M3G_RGBA) {
   1.527 +            m3gRaiseError(M3G_INTERFACE(background), M3G_INVALID_VALUE);
   1.528 +            return;
   1.529 +        }
   1.530 +
   1.531 +        background->crop.x = 0;
   1.532 +        background->crop.y = 0;
   1.533 +        background->crop.width = m3gGetWidth(image);
   1.534 +        background->crop.height = m3gGetHeight(image);
   1.535 +    }
   1.536 +
   1.537 +    M3G_ASSIGN_REF(background->image, image);
   1.538 +}
   1.539 +
   1.540 +/*!
   1.541 + * \brief Gets background image.
   1.542 + *
   1.543 + * \param handle        Background object
   1.544 + * \return              Image2D object or NULL
   1.545 + */
   1.546 +
   1.547 +/*@access M3GObject@*/
   1.548 +M3G_API M3GImage m3gGetBgImage(M3GBackground handle)
   1.549 +{
   1.550 +    Background *bg = (Background *) handle;
   1.551 +    M3G_VALIDATE_OBJECT(bg);
   1.552 +
   1.553 +    return (M3GImage) bg->image;
   1.554 +}
   1.555 +
   1.556 +/*!
   1.557 + * \brief Gets background color as ARGB.
   1.558 + *
   1.559 + * \param handle        Background object
   1.560 + * \return              ARGB color
   1.561 + */
   1.562 +
   1.563 +/*@access M3Gobject@*/
   1.564 +M3G_API M3Guint m3gGetBgColor(M3GBackground handle)
   1.565 +{
   1.566 +    Background *background = (Background *) handle;
   1.567 +    M3G_VALIDATE_OBJECT(background);
   1.568 +
   1.569 +    return background->color;
   1.570 +}
   1.571 +
   1.572 +/*!
   1.573 + * \brief Gets background image x or y mode.
   1.574 + *
   1.575 + * \param handle        Background object
   1.576 + * \param which         which mode to return
   1.577 + *                      \arg M3G_GET_MODEX
   1.578 + *                      \arg M3G_GET_MODEY
   1.579 + * \return              image x or y mode
   1.580 + */
   1.581 +
   1.582 +/*@access M3Gobject@*/
   1.583 +M3G_API M3Gint m3gGetBgMode(M3GBackground handle, M3Gint which)
   1.584 +{
   1.585 +    Background *background = (Background *) handle;
   1.586 +    M3G_VALIDATE_OBJECT(background);
   1.587 +
   1.588 +    switch(which) {
   1.589 +        case M3G_GET_MODEX:
   1.590 +            return background->modeX;
   1.591 +        case M3G_GET_MODEY:
   1.592 +        default:
   1.593 +            return background->modeY;
   1.594 +    }
   1.595 +}
   1.596 +
   1.597 +/*!
   1.598 + * \brief Gets background image crop parameter.
   1.599 + *
   1.600 + * \param handle        Background object
   1.601 + * \param which         which crop parameter to return
   1.602 + *                      \arg M3G_GET_CROPX
   1.603 + *                      \arg M3G_GET_CROPY
   1.604 + *                      \arg M3G_GET_CROPWIDTH
   1.605 + *                      \arg M3G_GET_CROPHEIGHT
   1.606 + * \return              image crop parameter
   1.607 + */
   1.608 +
   1.609 +/*@access M3Gobject@*/
   1.610 +M3G_API M3Gint m3gGetBgCrop(M3GBackground handle, M3Gint which)
   1.611 +{
   1.612 +    Background *background = (Background *) handle;
   1.613 +    M3G_VALIDATE_OBJECT(background);
   1.614 +
   1.615 +    switch(which) {
   1.616 +        case M3G_GET_CROPX:
   1.617 +            return background->crop.x;
   1.618 +        case M3G_GET_CROPY:
   1.619 +            return background->crop.y;
   1.620 +        case M3G_GET_CROPWIDTH:
   1.621 +            return background->crop.width;
   1.622 +        case M3G_GET_CROPHEIGHT:
   1.623 +        default:
   1.624 +            return background->crop.height;
   1.625 +    }
   1.626 +}
   1.627 +
   1.628 +/*!
   1.629 + * \brief Sets background color or depth clear enable.
   1.630 + *
   1.631 + * \param handle        Background object
   1.632 + * \param which         which clear to enable
   1.633 + *                      \arg M3G_SETGET_COLORCLEAR
   1.634 + *                      \arg M3G_SETGET_DEPTHCLEAR
   1.635 + * \param enable        clear enable/disable
   1.636 + */
   1.637 +
   1.638 +/*@access M3Gobject@*/
   1.639 +M3G_API void m3gSetBgEnable(M3GBackground handle, M3Gint which, M3Gbool enable)
   1.640 +{
   1.641 +    Background *background = (Background *) handle;
   1.642 +    M3G_VALIDATE_OBJECT(background);
   1.643 +
   1.644 +    switch(which) {
   1.645 +        case M3G_SETGET_COLORCLEAR:
   1.646 +            background->colorClearEnable = enable;
   1.647 +            break;
   1.648 +        case M3G_SETGET_DEPTHCLEAR:
   1.649 +        default:
   1.650 +            background->depthClearEnable = enable;
   1.651 +            break;
   1.652 +    }
   1.653 +}
   1.654 +
   1.655 +/*!
   1.656 + * \brief Gets background color or depth clear enable.
   1.657 + *
   1.658 + * \param handle        Background object
   1.659 + * \param which         which clear to return
   1.660 + *                      \arg M3G_SETGET_COLORCLEAR
   1.661 + *                      \arg M3G_SETGET_DEPTHCLEAR
   1.662 + * \return              clear enabled
   1.663 + */
   1.664 +
   1.665 +/*@access M3Gobject@*/
   1.666 +M3G_API M3Gbool m3gIsBgEnabled(M3GBackground handle, M3Gint which)
   1.667 +{
   1.668 +    Background *background = (Background *) handle;
   1.669 +    M3G_VALIDATE_OBJECT(background);
   1.670 +
   1.671 +    switch(which) {
   1.672 +        case M3G_SETGET_COLORCLEAR:
   1.673 +            return background->colorClearEnable;
   1.674 +        case M3G_SETGET_DEPTHCLEAR:
   1.675 +        default:
   1.676 +            return background->depthClearEnable;
   1.677 +    }
   1.678 +}
   1.679 +