os/graphics/m3g/m3gcore11/src/m3g_background.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: Background implementation
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/*!
sl@0
    20
 * \internal
sl@0
    21
 * \file
sl@0
    22
 * \brief Background implementation
sl@0
    23
 */
sl@0
    24
sl@0
    25
#ifndef M3G_CORE_INCLUDE
sl@0
    26
#   error included by m3g_core.c; do not compile separately.
sl@0
    27
#endif
sl@0
    28
sl@0
    29
#include "m3g_background.h"
sl@0
    30
#include "m3g_image.h"
sl@0
    31
#include "m3g_memory.h"
sl@0
    32
#include "m3g_animationtrack.h"
sl@0
    33
#include "m3g_rendercontext.h"
sl@0
    34
sl@0
    35
/*----------------------------------------------------------------------
sl@0
    36
 * Internal functions
sl@0
    37
 *--------------------------------------------------------------------*/
sl@0
    38
sl@0
    39
/*!
sl@0
    40
 * \internal
sl@0
    41
 * \brief Destroys this Background object.
sl@0
    42
 *
sl@0
    43
 * \param obj Background object
sl@0
    44
 */
sl@0
    45
static void m3gDestroyBackground(Object *obj)
sl@0
    46
{
sl@0
    47
    Background *background = (Background *) obj;
sl@0
    48
    M3G_VALIDATE_OBJECT(background);
sl@0
    49
sl@0
    50
    M3G_ASSIGN_REF(background->image, NULL);
sl@0
    51
    m3gDestroyObject(obj);
sl@0
    52
}
sl@0
    53
sl@0
    54
/*!
sl@0
    55
 * \internal
sl@0
    56
 * \brief Applies background color and image
sl@0
    57
 * using a textured quad.
sl@0
    58
 *
sl@0
    59
 * \param ctx           render context
sl@0
    60
 * \param background    Background object
sl@0
    61
 */
sl@0
    62
static void m3gApplyBackground(RenderContext *ctx, Background *background)
sl@0
    63
{
sl@0
    64
    GLbitfield glBits = 0;
sl@0
    65
    GLfixed temp[4];
sl@0
    66
    
sl@0
    67
    if (background->depthClearEnable) {
sl@0
    68
        glBits |= GL_DEPTH_BUFFER_BIT;
sl@0
    69
    }
sl@0
    70
sl@0
    71
    /* Skip color buffer clearing if the background image
sl@0
    72
     * fills the whole viewport. This is guaranteed to happen
sl@0
    73
     * if the crop rectangle is non-zero and both X and Y
sl@0
    74
     * wrapping modes are REPEAT. */
sl@0
    75
    
sl@0
    76
    if (background->colorClearEnable) {
sl@0
    77
        if (background->image == NULL ||
sl@0
    78
            background->crop.width == 0 ||
sl@0
    79
            background->crop.height == 0 ||
sl@0
    80
            background->modeX == M3G_BORDER ||
sl@0
    81
            background->modeY == M3G_BORDER)
sl@0
    82
        {
sl@0
    83
            glBits |= GL_COLOR_BUFFER_BIT;
sl@0
    84
            m3gGLColor(background->color, temp);
sl@0
    85
            glClearColorx(temp[0], temp[1], temp[2], temp[3]);
sl@0
    86
        }
sl@0
    87
    }
sl@0
    88
    
sl@0
    89
    /* Clear color and/or depth buffer (or neither) */
sl@0
    90
    glClear(glBits);
sl@0
    91
sl@0
    92
    /* Apply background image using a quad that
sl@0
    93
       fills the viewport */
sl@0
    94
sl@0
    95
    if (background->colorClearEnable &&
sl@0
    96
        background->image != NULL &&
sl@0
    97
        background->crop.width != 0 && 
sl@0
    98
        background->crop.height != 0)
sl@0
    99
    {
sl@0
   100
        {
sl@0
   101
            /* Texture coordinates */
sl@0
   102
            M3Gshort texvert[4 * 2];
sl@0
   103
            /* Quad that fills the viewport */
sl@0
   104
            M3Gint vert[4 * 3]   = { -65536,  65536, 0,
sl@0
   105
                                     -65536, -65536, 0,
sl@0
   106
                                      65536,  65536, 0,
sl@0
   107
                                      65536, -65536, 0 };
sl@0
   108
            Rect rImage, rIntersection;
sl@0
   109
            M3Gbool intersects;
sl@0
   110
            Image *imagePow2;
sl@0
   111
sl@0
   112
            /* Get power of two image */
sl@0
   113
            imagePow2 = m3gGetPowerOfTwoImage(background->image);
sl@0
   114
            /* If NULL -> out of memory */
sl@0
   115
            if (!imagePow2) {
sl@0
   116
                return;
sl@0
   117
            }
sl@0
   118
sl@0
   119
            rImage.x = 0;
sl@0
   120
            rImage.y = 0;
sl@0
   121
            rImage.width = m3gGetWidth(background->image);
sl@0
   122
            rImage.height = m3gGetHeight(background->image);
sl@0
   123
sl@0
   124
            /* Intersection of source image and crop rectangle */
sl@0
   125
            intersects = m3gIntersectRectangle(&rIntersection, &rImage, &background->crop);
sl@0
   126
sl@0
   127
            /* Setup X vertices and texture S coordinates */
sl@0
   128
            if (background->modeX == M3G_BORDER) {
sl@0
   129
                /* If both modes are border and no intersection ->
sl@0
   130
                   nothing to draw */
sl@0
   131
                if (background->modeY == M3G_BORDER && !intersects) {
sl@0
   132
                    return;
sl@0
   133
                }
sl@0
   134
sl@0
   135
                texvert[0 * 2 + 0] = (M3Gshort) rIntersection.x;
sl@0
   136
                texvert[1 * 2 + 0] = (M3Gshort) rIntersection.x;
sl@0
   137
                texvert[2 * 2 + 0] = (M3Gshort) (rIntersection.x + rIntersection.width);
sl@0
   138
                texvert[3 * 2 + 0] = (M3Gshort) (rIntersection.x + rIntersection.width);
sl@0
   139
sl@0
   140
                vert[0 * 3 + 0] = -65536 + 2 * 65536 * (rIntersection.x - background->crop.x) / background->crop.width;
sl@0
   141
                vert[1 * 3 + 0] = vert[0 * 3 + 0];
sl@0
   142
                vert[2 * 3 + 0] = vert[0 * 3 + 0] + 2 * 65536 * rIntersection.width / background->crop.width;
sl@0
   143
                vert[3 * 3 + 0] = vert[2 * 3 + 0];
sl@0
   144
            }
sl@0
   145
            else {
sl@0
   146
                /* In repeat mode texture coordinates are directly crop rectangle coordinates */
sl@0
   147
                texvert[0 * 2 + 0] = (M3Gshort) background->crop.x;
sl@0
   148
                texvert[1 * 2 + 0] = (M3Gshort) background->crop.x;
sl@0
   149
                texvert[2 * 2 + 0] = (M3Gshort) (background->crop.x + background->crop.width);
sl@0
   150
                texvert[3 * 2 + 0] = (M3Gshort) (background->crop.x + background->crop.width);
sl@0
   151
            }
sl@0
   152
sl@0
   153
            /* Setup Y vertices and texture T coordinates */
sl@0
   154
            if (background->modeY == M3G_BORDER) {
sl@0
   155
                texvert[0 * 2 + 1] = (M3Gshort) rIntersection.y;
sl@0
   156
                texvert[1 * 2 + 1] = (M3Gshort) (rIntersection.y + rIntersection.height);
sl@0
   157
                texvert[2 * 2 + 1] = (M3Gshort) rIntersection.y;
sl@0
   158
                texvert[3 * 2 + 1] = (M3Gshort) (rIntersection.y + rIntersection.height);
sl@0
   159
sl@0
   160
sl@0
   161
                vert[0 * 3 + 1] =  65536 - 2 * 65536 * (rIntersection.y - background->crop.y) / background->crop.height;
sl@0
   162
                vert[1 * 3 + 1] = vert[0 * 3 + 1] - 2 * 65536 * rIntersection.height / background->crop.height;
sl@0
   163
                vert[2 * 3 + 1] = vert[0 * 3 + 1];
sl@0
   164
                vert[3 * 3 + 1] = vert[1 * 3 + 1];
sl@0
   165
            }
sl@0
   166
            else {
sl@0
   167
                /* In repeat mode texture coordinates are directly crop rectangle coordinates */
sl@0
   168
                texvert[0 * 2 + 1] = (M3Gshort) background->crop.y;
sl@0
   169
                texvert[1 * 2 + 1] = (M3Gshort) (background->crop.y + background->crop.height);
sl@0
   170
                texvert[2 * 2 + 1] = (M3Gshort) background->crop.y;
sl@0
   171
                texvert[3 * 2 + 1] = (M3Gshort) (background->crop.y + background->crop.height);
sl@0
   172
            }
sl@0
   173
sl@0
   174
            /* Disable unwanted state and depth writes */
sl@0
   175
            m3gApplyAppearance(NULL, ctx, 0);
sl@0
   176
            glDepthMask(GL_FALSE);
sl@0
   177
sl@0
   178
            /* Disable color array, normals and textures*/
sl@0
   179
            glDisableClientState(GL_COLOR_ARRAY);
sl@0
   180
            glDisableClientState(GL_NORMAL_ARRAY);
sl@0
   181
        
sl@0
   182
            /* Background image to texture unit 0 */
sl@0
   183
            glClientActiveTexture(GL_TEXTURE0);
sl@0
   184
            glActiveTexture(GL_TEXTURE0);
sl@0
   185
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
sl@0
   186
            glTexCoordPointer(2, GL_SHORT, 0, texvert);
sl@0
   187
            glEnable(GL_TEXTURE_2D);
sl@0
   188
            glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLfixed) GL_REPLACE);
sl@0
   189
            m3gBindTextureImage(imagePow2,
sl@0
   190
                                M3G_FILTER_BASE_LEVEL,
sl@0
   191
                                m3gIsAccelerated(ctx) ? M3G_FILTER_LINEAR : M3G_FILTER_NEAREST);
sl@0
   192
sl@0
   193
            /* Set wrapping */
sl@0
   194
            if (background->modeX == M3G_REPEAT) {
sl@0
   195
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
sl@0
   196
            }
sl@0
   197
            else {
sl@0
   198
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
sl@0
   199
            }
sl@0
   200
    
sl@0
   201
            if (background->modeY == M3G_REPEAT) {
sl@0
   202
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
sl@0
   203
            }
sl@0
   204
            else {
sl@0
   205
                glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
sl@0
   206
            }
sl@0
   207
sl@0
   208
            /* Texture matrix scale */
sl@0
   209
            glMatrixMode(GL_TEXTURE);
sl@0
   210
            glLoadIdentity();
sl@0
   211
            glScalef(   m3gRcp((M3Gfloat)m3gGetWidth(background->image)),
sl@0
   212
                        m3gRcp((M3Gfloat)m3gGetHeight(background->image)),
sl@0
   213
                        1.f);
sl@0
   214
            glMatrixMode(GL_MODELVIEW);
sl@0
   215
sl@0
   216
            /* Load vertices */
sl@0
   217
            glEnableClientState(GL_VERTEX_ARRAY);
sl@0
   218
            glVertexPointer(3, GL_FIXED, 0, vert);
sl@0
   219
        
sl@0
   220
            /* Set up an identity modelview and projection */
sl@0
   221
            m3gPushScreenSpace(ctx, M3G_FALSE);
sl@0
   222
sl@0
   223
            /* Load indices -> draws the background */
sl@0
   224
            M3G_BEGIN_PROFILE(M3G_INTERFACE(ctx), M3G_PROFILE_NGL_DRAW);
sl@0
   225
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
sl@0
   226
            M3G_END_PROFILE(M3G_INTERFACE(ctx), M3G_PROFILE_NGL_DRAW);
sl@0
   227
        
sl@0
   228
            m3gPopSpace(ctx);
sl@0
   229
            m3gReleaseTextureImage(imagePow2);
sl@0
   230
        }
sl@0
   231
    }
sl@0
   232
}
sl@0
   233
sl@0
   234
/*!
sl@0
   235
 * \internal
sl@0
   236
 * \brief Overloaded Object3D method.
sl@0
   237
 *
sl@0
   238
 * \param property      animation property
sl@0
   239
 * \retval M3G_TRUE     property supported
sl@0
   240
 * \retval M3G_FALSE    property not supported
sl@0
   241
 */
sl@0
   242
static M3Gbool m3gBackgroundIsCompatible(M3Gint property)
sl@0
   243
{
sl@0
   244
    switch (property) {
sl@0
   245
    case M3G_ANIM_ALPHA:
sl@0
   246
    case M3G_ANIM_COLOR:
sl@0
   247
    case M3G_ANIM_CROP:
sl@0
   248
        return M3G_TRUE;
sl@0
   249
    default:
sl@0
   250
        return m3gObjectIsCompatible(property);
sl@0
   251
    }
sl@0
   252
}
sl@0
   253
sl@0
   254
/*!
sl@0
   255
 * \internal
sl@0
   256
 * \brief Overloaded Object3D method.
sl@0
   257
 *
sl@0
   258
 * \param self          Background object
sl@0
   259
 * \param property      animation property
sl@0
   260
 * \param valueSize     size of value array
sl@0
   261
 * \param value         value array
sl@0
   262
 */
sl@0
   263
static void m3gBackgroundUpdateProperty(Object *self,
sl@0
   264
                                        M3Gint property,
sl@0
   265
                                        M3Gint valueSize,
sl@0
   266
                                        const M3Gfloat *value)
sl@0
   267
{
sl@0
   268
    Background *background = (Background *)self;
sl@0
   269
    M3G_VALIDATE_OBJECT(background);
sl@0
   270
    M3G_ASSERT_PTR(value);
sl@0
   271
    
sl@0
   272
    switch (property) {
sl@0
   273
    case M3G_ANIM_ALPHA:
sl@0
   274
        M3G_ASSERT(valueSize >= 1);
sl@0
   275
        background->color = m3gAlpha1f(value[0])
sl@0
   276
            & (background->color | M3G_ALPHA_MASK);
sl@0
   277
        break;
sl@0
   278
    case M3G_ANIM_COLOR:
sl@0
   279
        M3G_ASSERT(valueSize >= 3);
sl@0
   280
        background->color = m3gColor3f(value[0], value[1], value[2])
sl@0
   281
            & (background->color | M3G_RGB_MASK);
sl@0
   282
        break;
sl@0
   283
    case M3G_ANIM_CROP:
sl@0
   284
        M3G_ASSERT(valueSize >= 2);
sl@0
   285
        background->crop.x = m3gRoundToInt(value[0]);
sl@0
   286
        background->crop.y = m3gRoundToInt(value[1]);
sl@0
   287
        if (valueSize > 2) {
sl@0
   288
            M3G_ASSERT(valueSize >= 4);
sl@0
   289
            background->crop.width =
sl@0
   290
                (value[2] < 0) ? 0 : m3gRoundToInt(value[2]);
sl@0
   291
            background->crop.height =
sl@0
   292
                (value[3] < 0) ? 0 : m3gRoundToInt(value[3]);
sl@0
   293
        }
sl@0
   294
        break;
sl@0
   295
    default:
sl@0
   296
        m3gObjectUpdateProperty(self, property, valueSize, value);
sl@0
   297
    }
sl@0
   298
}
sl@0
   299
sl@0
   300
/*!
sl@0
   301
 * \internal
sl@0
   302
 * \brief Overloaded Object3D method.
sl@0
   303
 *
sl@0
   304
 * \param self Background object
sl@0
   305
 * \param references array of reference objects
sl@0
   306
 * \return number of references
sl@0
   307
 */
sl@0
   308
static M3Gint m3gBackgroundDoGetReferences(Object *self, Object **references)
sl@0
   309
{
sl@0
   310
    Background *bg = (Background *)self;
sl@0
   311
    M3Gint num = m3gObjectDoGetReferences(self, references);
sl@0
   312
    if (bg->image != NULL) {
sl@0
   313
        if (references != NULL)
sl@0
   314
            references[num] = (Object *)bg->image;
sl@0
   315
        num++;
sl@0
   316
    }
sl@0
   317
    return num;
sl@0
   318
}
sl@0
   319
sl@0
   320
/*!
sl@0
   321
 * \internal
sl@0
   322
 * \brief Overloaded Object3D method.
sl@0
   323
 */
sl@0
   324
static Object *m3gBackgroundFindID(Object *self, M3Gint userID)
sl@0
   325
{
sl@0
   326
    Background *bg = (Background *)self;
sl@0
   327
    Object *found = m3gObjectFindID(self, userID);
sl@0
   328
sl@0
   329
    if (!found && bg->image) {
sl@0
   330
        found = m3gFindID((Object*) bg->image, userID);
sl@0
   331
    }
sl@0
   332
    return found;
sl@0
   333
}
sl@0
   334
sl@0
   335
/*!
sl@0
   336
 * \internal
sl@0
   337
 * \brief Overloaded Object3D method.
sl@0
   338
 *
sl@0
   339
 * \param originalObj original Background object
sl@0
   340
 * \param cloneObj pointer to cloned Background object
sl@0
   341
 * \param pairs array for all object-duplicate pairs
sl@0
   342
 * \param numPairs number of pairs
sl@0
   343
 */
sl@0
   344
static M3Gbool m3gBackgroundDuplicate(const Object *originalObj,
sl@0
   345
                                      Object **cloneObj,
sl@0
   346
                                      Object **pairs,
sl@0
   347
                                      M3Gint *numPairs)
sl@0
   348
{
sl@0
   349
    Background *original = (Background *)originalObj;
sl@0
   350
    Background *clone = (Background *)m3gCreateBackground(originalObj->interface);
sl@0
   351
    *cloneObj = (Object *)clone;
sl@0
   352
    if (*cloneObj == NULL) {
sl@0
   353
        return M3G_FALSE;
sl@0
   354
    }
sl@0
   355
sl@0
   356
    if (m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) {
sl@0
   357
        clone->color = original->color;
sl@0
   358
        clone->modeX = original->modeX;
sl@0
   359
        clone->modeY = original->modeY;
sl@0
   360
        clone->crop = original->crop;
sl@0
   361
        clone->colorClearEnable = original->colorClearEnable;
sl@0
   362
        clone->depthClearEnable = original->depthClearEnable;
sl@0
   363
        M3G_ASSIGN_REF(clone->image, original->image);
sl@0
   364
        return M3G_TRUE;
sl@0
   365
    }
sl@0
   366
    else {
sl@0
   367
        return M3G_FALSE;
sl@0
   368
    }
sl@0
   369
}
sl@0
   370
sl@0
   371
/*!
sl@0
   372
 * \internal
sl@0
   373
 * \brief Initializes a Background object. See specification
sl@0
   374
 * for default values.
sl@0
   375
 *
sl@0
   376
 * \param m3g           M3G interface
sl@0
   377
 * \param background    Background object
sl@0
   378
 */
sl@0
   379
static void m3gInitBackground(Interface *m3g, Background *background)
sl@0
   380
{
sl@0
   381
    /* Background is derived from Object */
sl@0
   382
    m3gInitObject(&background->object, m3g, M3G_CLASS_BACKGROUND);
sl@0
   383
sl@0
   384
    background->modeX = M3G_BORDER; 
sl@0
   385
    background->modeY = M3G_BORDER; 
sl@0
   386
    background->colorClearEnable = M3G_TRUE;
sl@0
   387
    background->depthClearEnable = M3G_TRUE;
sl@0
   388
}
sl@0
   389
sl@0
   390
/*----------------------------------------------------------------------
sl@0
   391
 * Virtual function table
sl@0
   392
 *--------------------------------------------------------------------*/
sl@0
   393
sl@0
   394
static const ObjectVFTable m3gvf_Background = {
sl@0
   395
    m3gObjectApplyAnimation,
sl@0
   396
    m3gBackgroundIsCompatible,
sl@0
   397
    m3gBackgroundUpdateProperty,
sl@0
   398
    m3gBackgroundDoGetReferences,
sl@0
   399
    m3gBackgroundFindID,
sl@0
   400
    m3gBackgroundDuplicate,
sl@0
   401
    m3gDestroyBackground
sl@0
   402
};
sl@0
   403
sl@0
   404
sl@0
   405
/*----------------------------------------------------------------------
sl@0
   406
 * Public API functions
sl@0
   407
 *--------------------------------------------------------------------*/
sl@0
   408
sl@0
   409
/*!
sl@0
   410
 * \brief Creates a Background object.
sl@0
   411
 *
sl@0
   412
 * \param interface     M3G interface
sl@0
   413
 * \retval Background new Background object
sl@0
   414
 * \retval NULL Background creating failed
sl@0
   415
 */
sl@0
   416
sl@0
   417
/*@access M3GInterface@*/
sl@0
   418
/*@access M3Gobject@*/
sl@0
   419
M3G_API M3GBackground m3gCreateBackground(M3GInterface interface)
sl@0
   420
{
sl@0
   421
    Interface *m3g = (Interface *) interface;
sl@0
   422
    M3G_VALIDATE_INTERFACE(m3g);
sl@0
   423
sl@0
   424
    {
sl@0
   425
        Background *background =  m3gAllocZ(m3g, sizeof(Background));
sl@0
   426
    
sl@0
   427
        if (background != NULL) {
sl@0
   428
            m3gInitBackground(m3g, background);
sl@0
   429
        }
sl@0
   430
sl@0
   431
        return (M3GBackground) background;
sl@0
   432
    }
sl@0
   433
}
sl@0
   434
sl@0
   435
/*!
sl@0
   436
 * \brief Sets background color.
sl@0
   437
 *
sl@0
   438
 * \param handle        Background object
sl@0
   439
 * \param ARGB          background color as ARGB
sl@0
   440
 */
sl@0
   441
sl@0
   442
/*@access M3Gobject@*/
sl@0
   443
M3G_API void m3gSetBgColor(M3GBackground handle, M3Guint ARGB)
sl@0
   444
{
sl@0
   445
    Background *background = (Background *) handle;
sl@0
   446
    M3G_VALIDATE_OBJECT(background);
sl@0
   447
    
sl@0
   448
    background->color = ARGB;
sl@0
   449
}
sl@0
   450
sl@0
   451
/*!
sl@0
   452
 * \brief Sets background image x and y mode.
sl@0
   453
 *
sl@0
   454
 * \param handle        Background object
sl@0
   455
 * \param modeX         Image X mode
sl@0
   456
 * \param modeY         Image Y mode
sl@0
   457
 */
sl@0
   458
sl@0
   459
/*@access M3Gobject@*/
sl@0
   460
M3G_API void m3gSetBgMode(M3GBackground handle, M3Gint modeX, M3Gint modeY)
sl@0
   461
{
sl@0
   462
    Background *background = (Background *) handle;
sl@0
   463
    M3G_VALIDATE_OBJECT(background);
sl@0
   464
    
sl@0
   465
    /* Check for errors */
sl@0
   466
    if (modeX < M3G_BORDER || modeX > M3G_REPEAT ||
sl@0
   467
        modeY < M3G_BORDER || modeY > M3G_REPEAT) {
sl@0
   468
        m3gRaiseError(M3G_INTERFACE(background), M3G_INVALID_VALUE);
sl@0
   469
        return;
sl@0
   470
    }
sl@0
   471
sl@0
   472
    background->modeX = modeX;
sl@0
   473
    background->modeY = modeY;
sl@0
   474
}
sl@0
   475
sl@0
   476
/*!
sl@0
   477
 * \brief Sets background image crop rectangle.
sl@0
   478
 *
sl@0
   479
 * \param handle        Background object
sl@0
   480
 * \param cropX         crop upper left x
sl@0
   481
 * \param cropY         crop upper left y
sl@0
   482
 * \param width         crop width
sl@0
   483
 * \param height        crop height
sl@0
   484
 */
sl@0
   485
sl@0
   486
/*@access M3Gobject@*/
sl@0
   487
M3G_API void m3gSetBgCrop(M3GBackground handle,
sl@0
   488
                          M3Gint cropX, M3Gint cropY,
sl@0
   489
                          M3Gint width, M3Gint height)
sl@0
   490
{
sl@0
   491
    Background *background = (Background *) handle;
sl@0
   492
    M3G_VALIDATE_OBJECT(background);
sl@0
   493
sl@0
   494
    /* Check for errors */
sl@0
   495
    if (width < 0 || height < 0) {
sl@0
   496
        m3gRaiseError(M3G_INTERFACE(background), M3G_INVALID_VALUE);
sl@0
   497
        return;
sl@0
   498
    }
sl@0
   499
sl@0
   500
    background->crop.x = cropX;
sl@0
   501
    background->crop.y = cropY;
sl@0
   502
    background->crop.width = width;
sl@0
   503
    background->crop.height = height;
sl@0
   504
}
sl@0
   505
sl@0
   506
/*!
sl@0
   507
 * \brief Sets background image.
sl@0
   508
 *
sl@0
   509
 * \param handle        Background object
sl@0
   510
 * \param hImage        Image2D object or NULL
sl@0
   511
 */
sl@0
   512
sl@0
   513
/*@access M3Gobject@*/
sl@0
   514
M3G_API void m3gSetBgImage(M3GBackground handle, M3GImage hImage)
sl@0
   515
{
sl@0
   516
    Background *background = (Background *) handle;
sl@0
   517
    Image *image = (Image *)hImage;
sl@0
   518
    M3G_VALIDATE_OBJECT(background);
sl@0
   519
sl@0
   520
    if (image != NULL) {
sl@0
   521
        /* Check allowed formats */
sl@0
   522
        if (m3gGetFormat(image) != M3G_RGB &&
sl@0
   523
            m3gGetFormat(image) != M3G_RGBA) {
sl@0
   524
            m3gRaiseError(M3G_INTERFACE(background), M3G_INVALID_VALUE);
sl@0
   525
            return;
sl@0
   526
        }
sl@0
   527
sl@0
   528
        background->crop.x = 0;
sl@0
   529
        background->crop.y = 0;
sl@0
   530
        background->crop.width = m3gGetWidth(image);
sl@0
   531
        background->crop.height = m3gGetHeight(image);
sl@0
   532
    }
sl@0
   533
sl@0
   534
    M3G_ASSIGN_REF(background->image, image);
sl@0
   535
}
sl@0
   536
sl@0
   537
/*!
sl@0
   538
 * \brief Gets background image.
sl@0
   539
 *
sl@0
   540
 * \param handle        Background object
sl@0
   541
 * \return              Image2D object or NULL
sl@0
   542
 */
sl@0
   543
sl@0
   544
/*@access M3GObject@*/
sl@0
   545
M3G_API M3GImage m3gGetBgImage(M3GBackground handle)
sl@0
   546
{
sl@0
   547
    Background *bg = (Background *) handle;
sl@0
   548
    M3G_VALIDATE_OBJECT(bg);
sl@0
   549
sl@0
   550
    return (M3GImage) bg->image;
sl@0
   551
}
sl@0
   552
sl@0
   553
/*!
sl@0
   554
 * \brief Gets background color as ARGB.
sl@0
   555
 *
sl@0
   556
 * \param handle        Background object
sl@0
   557
 * \return              ARGB color
sl@0
   558
 */
sl@0
   559
sl@0
   560
/*@access M3Gobject@*/
sl@0
   561
M3G_API M3Guint m3gGetBgColor(M3GBackground handle)
sl@0
   562
{
sl@0
   563
    Background *background = (Background *) handle;
sl@0
   564
    M3G_VALIDATE_OBJECT(background);
sl@0
   565
sl@0
   566
    return background->color;
sl@0
   567
}
sl@0
   568
sl@0
   569
/*!
sl@0
   570
 * \brief Gets background image x or y mode.
sl@0
   571
 *
sl@0
   572
 * \param handle        Background object
sl@0
   573
 * \param which         which mode to return
sl@0
   574
 *                      \arg M3G_GET_MODEX
sl@0
   575
 *                      \arg M3G_GET_MODEY
sl@0
   576
 * \return              image x or y mode
sl@0
   577
 */
sl@0
   578
sl@0
   579
/*@access M3Gobject@*/
sl@0
   580
M3G_API M3Gint m3gGetBgMode(M3GBackground handle, M3Gint which)
sl@0
   581
{
sl@0
   582
    Background *background = (Background *) handle;
sl@0
   583
    M3G_VALIDATE_OBJECT(background);
sl@0
   584
sl@0
   585
    switch(which) {
sl@0
   586
        case M3G_GET_MODEX:
sl@0
   587
            return background->modeX;
sl@0
   588
        case M3G_GET_MODEY:
sl@0
   589
        default:
sl@0
   590
            return background->modeY;
sl@0
   591
    }
sl@0
   592
}
sl@0
   593
sl@0
   594
/*!
sl@0
   595
 * \brief Gets background image crop parameter.
sl@0
   596
 *
sl@0
   597
 * \param handle        Background object
sl@0
   598
 * \param which         which crop parameter to return
sl@0
   599
 *                      \arg M3G_GET_CROPX
sl@0
   600
 *                      \arg M3G_GET_CROPY
sl@0
   601
 *                      \arg M3G_GET_CROPWIDTH
sl@0
   602
 *                      \arg M3G_GET_CROPHEIGHT
sl@0
   603
 * \return              image crop parameter
sl@0
   604
 */
sl@0
   605
sl@0
   606
/*@access M3Gobject@*/
sl@0
   607
M3G_API M3Gint m3gGetBgCrop(M3GBackground handle, M3Gint which)
sl@0
   608
{
sl@0
   609
    Background *background = (Background *) handle;
sl@0
   610
    M3G_VALIDATE_OBJECT(background);
sl@0
   611
sl@0
   612
    switch(which) {
sl@0
   613
        case M3G_GET_CROPX:
sl@0
   614
            return background->crop.x;
sl@0
   615
        case M3G_GET_CROPY:
sl@0
   616
            return background->crop.y;
sl@0
   617
        case M3G_GET_CROPWIDTH:
sl@0
   618
            return background->crop.width;
sl@0
   619
        case M3G_GET_CROPHEIGHT:
sl@0
   620
        default:
sl@0
   621
            return background->crop.height;
sl@0
   622
    }
sl@0
   623
}
sl@0
   624
sl@0
   625
/*!
sl@0
   626
 * \brief Sets background color or depth clear enable.
sl@0
   627
 *
sl@0
   628
 * \param handle        Background object
sl@0
   629
 * \param which         which clear to enable
sl@0
   630
 *                      \arg M3G_SETGET_COLORCLEAR
sl@0
   631
 *                      \arg M3G_SETGET_DEPTHCLEAR
sl@0
   632
 * \param enable        clear enable/disable
sl@0
   633
 */
sl@0
   634
sl@0
   635
/*@access M3Gobject@*/
sl@0
   636
M3G_API void m3gSetBgEnable(M3GBackground handle, M3Gint which, M3Gbool enable)
sl@0
   637
{
sl@0
   638
    Background *background = (Background *) handle;
sl@0
   639
    M3G_VALIDATE_OBJECT(background);
sl@0
   640
sl@0
   641
    switch(which) {
sl@0
   642
        case M3G_SETGET_COLORCLEAR:
sl@0
   643
            background->colorClearEnable = enable;
sl@0
   644
            break;
sl@0
   645
        case M3G_SETGET_DEPTHCLEAR:
sl@0
   646
        default:
sl@0
   647
            background->depthClearEnable = enable;
sl@0
   648
            break;
sl@0
   649
    }
sl@0
   650
}
sl@0
   651
sl@0
   652
/*!
sl@0
   653
 * \brief Gets background color or depth clear enable.
sl@0
   654
 *
sl@0
   655
 * \param handle        Background object
sl@0
   656
 * \param which         which clear to return
sl@0
   657
 *                      \arg M3G_SETGET_COLORCLEAR
sl@0
   658
 *                      \arg M3G_SETGET_DEPTHCLEAR
sl@0
   659
 * \return              clear enabled
sl@0
   660
 */
sl@0
   661
sl@0
   662
/*@access M3Gobject@*/
sl@0
   663
M3G_API M3Gbool m3gIsBgEnabled(M3GBackground handle, M3Gint which)
sl@0
   664
{
sl@0
   665
    Background *background = (Background *) handle;
sl@0
   666
    M3G_VALIDATE_OBJECT(background);
sl@0
   667
sl@0
   668
    switch(which) {
sl@0
   669
        case M3G_SETGET_COLORCLEAR:
sl@0
   670
            return background->colorClearEnable;
sl@0
   671
        case M3G_SETGET_DEPTHCLEAR:
sl@0
   672
        default:
sl@0
   673
            return background->depthClearEnable;
sl@0
   674
    }
sl@0
   675
}
sl@0
   676