src/video/fbcon/SDL_fbmatrox.c
author Edgar Simo <bobbens@gmail.com>
Sun, 06 Jul 2008 17:06:37 +0000
branchgsoc2008_force_feedback
changeset 2498 ab567bd667bf
parent 1895 c121d94672cb
child 2698 e1da92da346c
permissions -rw-r--r--
Fixed various mistakes in the doxygen.
slouken@0
     1
/*
slouken@1312
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@1312
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1312
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@1312
    10
    This library is distributed in the hope that it will be useful,
slouken@1312
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1312
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@1312
    19
    Sam Lantinga
slouken@1312
    20
    slouken@libsdl.org
slouken@1312
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
#include "SDL_video.h"
slouken@1361
    25
#include "../SDL_blit.h"
slouken@0
    26
#include "SDL_fbmatrox.h"
slouken@0
    27
#include "matrox_mmio.h"
slouken@0
    28
slouken@0
    29
slouken@0
    30
/* Wait for vertical retrace - taken from the XFree86 Matrox driver */
slouken@1895
    31
static void
slouken@1895
    32
WaitVBL(_THIS)
slouken@0
    33
{
slouken@1895
    34
    int count;
slouken@0
    35
slouken@1895
    36
    /* find start of retrace */
slouken@1895
    37
    mga_waitidle();
slouken@1895
    38
    while ((mga_in8(0x1FDA) & 0x08));
slouken@1895
    39
    while (!(mga_in8(0x1FDA) & 0x08));
slouken@1895
    40
    /* wait until we're past the start */
slouken@1895
    41
    count = mga_in32(0x1E20) + 2;
slouken@1895
    42
    while (mga_in32(0x1E20) < count);
slouken@0
    43
}
slouken@1895
    44
static void
slouken@1895
    45
WaitIdle(_THIS)
slouken@106
    46
{
slouken@1895
    47
    mga_waitidle();
slouken@106
    48
}
slouken@0
    49
slouken@0
    50
/* Sets video mem colorkey and accelerated blit function */
slouken@1895
    51
static int
slouken@1895
    52
SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key)
slouken@0
    53
{
slouken@1895
    54
    return (0);
slouken@0
    55
}
slouken@0
    56
slouken@0
    57
/* Sets per surface hardware alpha value */
slouken@20
    58
#if 0
slouken@1895
    59
static int
slouken@1895
    60
SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 value)
slouken@0
    61
{
slouken@1895
    62
    return (0);
slouken@0
    63
}
slouken@20
    64
#endif
slouken@0
    65
slouken@1895
    66
static int
slouken@1895
    67
FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * rect, Uint32 color)
slouken@0
    68
{
slouken@1895
    69
    int dstX, dstY;
slouken@1895
    70
    Uint32 fxbndry;
slouken@1895
    71
    Uint32 ydstlen;
slouken@1895
    72
    Uint32 fillop;
slouken@0
    73
slouken@1895
    74
    /* Don't blit to the display surface when switched away */
slouken@1895
    75
    if (switched_away) {
slouken@1895
    76
        return -2;              /* no hardware access */
slouken@1895
    77
    }
slouken@1895
    78
    if (dst == this->screen) {
slouken@1895
    79
        SDL_mutexP(hw_lock);
slouken@1895
    80
    }
slouken@109
    81
slouken@1895
    82
    switch (dst->format->BytesPerPixel) {
slouken@1895
    83
    case 1:
slouken@1895
    84
        color |= (color << 8);
slouken@1895
    85
    case 2:
slouken@1895
    86
        color |= (color << 16);
slouken@1895
    87
        break;
slouken@1895
    88
    }
slouken@0
    89
slouken@1895
    90
    /* Set up the X/Y base coordinates */
slouken@1895
    91
    FB_dst_to_xy(this, dst, &dstX, &dstY);
slouken@0
    92
slouken@1895
    93
    /* Adjust for the current rectangle */
slouken@1895
    94
    dstX += rect->x;
slouken@1895
    95
    dstY += rect->y;
slouken@0
    96
slouken@1895
    97
    /* Set up the X boundaries */
slouken@1895
    98
    fxbndry = (dstX | ((dstX + rect->w) << 16));
slouken@0
    99
slouken@1895
   100
    /* Set up the Y boundaries */
slouken@1895
   101
    ydstlen = (rect->h | (dstY << 16));
slouken@0
   102
slouken@1895
   103
    /* Set up for color fill operation */
slouken@1895
   104
    fillop = MGADWG_TRAP | MGADWG_SOLID |
slouken@1895
   105
        MGADWG_ARZERO | MGADWG_SGNZERO | MGADWG_SHIFTZERO;
slouken@0
   106
slouken@1895
   107
    /* Execute the operations! */
slouken@1895
   108
    mga_wait(5);
slouken@1895
   109
    mga_out32(MGAREG_DWGCTL, fillop | MGADWG_REPLACE);
slouken@1895
   110
    mga_out32(MGAREG_FCOL, color);
slouken@1895
   111
    mga_out32(MGAREG_FXBNDRY, fxbndry);
slouken@1895
   112
    mga_out32(MGAREG_YDSTLEN + MGAREG_EXEC, ydstlen);
slouken@106
   113
slouken@1895
   114
    FB_AddBusySurface(dst);
slouken@0
   115
slouken@1895
   116
    if (dst == this->screen) {
slouken@1895
   117
        SDL_mutexV(hw_lock);
slouken@1895
   118
    }
slouken@1895
   119
    return (0);
slouken@0
   120
}
slouken@0
   121
slouken@1895
   122
static int
slouken@1895
   123
HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
slouken@1895
   124
            SDL_Surface * dst, SDL_Rect * dstrect)
slouken@0
   125
{
slouken@1895
   126
    SDL_VideoDevice *this = current_video;
slouken@1895
   127
    int pitch, w, h;
slouken@1895
   128
    int srcX, srcY;
slouken@1895
   129
    int dstX, dstY;
slouken@1895
   130
    Uint32 sign;
slouken@1895
   131
    Uint32 start, stop;
slouken@1895
   132
    int skip;
slouken@1895
   133
    Uint32 blitop;
slouken@0
   134
slouken@1895
   135
    /* FIXME: For now, only blit to display surface */
slouken@1895
   136
    if (dst->pitch != SDL_VideoSurface->pitch) {
slouken@1895
   137
        return (src->map->sw_blit(src, srcrect, dst, dstrect));
slouken@1895
   138
    }
slouken@0
   139
slouken@1895
   140
    /* Don't blit to the display surface when switched away */
slouken@1895
   141
    if (switched_away) {
slouken@1895
   142
        return -2;              /* no hardware access */
slouken@1895
   143
    }
slouken@1895
   144
    if (dst == this->screen) {
slouken@1895
   145
        SDL_mutexP(hw_lock);
slouken@1895
   146
    }
slouken@109
   147
slouken@1895
   148
    /* Calculate source and destination base coordinates (in pixels) */
slouken@1895
   149
    w = dstrect->w;
slouken@1895
   150
    h = dstrect->h;
slouken@1895
   151
    FB_dst_to_xy(this, src, &srcX, &srcY);
slouken@1895
   152
    FB_dst_to_xy(this, dst, &dstX, &dstY);
slouken@0
   153
slouken@1895
   154
    /* Adjust for the current blit rectangles */
slouken@1895
   155
    srcX += srcrect->x;
slouken@1895
   156
    srcY += srcrect->y;
slouken@1895
   157
    dstX += dstrect->x;
slouken@1895
   158
    dstY += dstrect->y;
slouken@1895
   159
    pitch = dst->pitch / dst->format->BytesPerPixel;
slouken@0
   160
slouken@1895
   161
    /* Set up the blit direction (sign) flags */
slouken@1895
   162
    sign = 0;
slouken@1895
   163
    if (srcX < dstX) {
slouken@1895
   164
        sign |= 1;
slouken@1895
   165
    }
slouken@1895
   166
    if (srcY < dstY) {
slouken@1895
   167
        sign |= 4;
slouken@1895
   168
        srcY += (h - 1);
slouken@1895
   169
        dstY += (h - 1);
slouken@1895
   170
    }
slouken@0
   171
slouken@1895
   172
    /* Set up the blit source row start, end, and skip (in pixels) */
slouken@1895
   173
    stop = start = (srcY * pitch) + srcX;
slouken@1895
   174
    if (srcX < dstX) {
slouken@1895
   175
        start += (w - 1);
slouken@1895
   176
    } else {
slouken@1895
   177
        stop += (w - 1);
slouken@1895
   178
    }
slouken@1895
   179
    if (srcY < dstY) {
slouken@1895
   180
        skip = -pitch;
slouken@1895
   181
    } else {
slouken@1895
   182
        skip = pitch;
slouken@1895
   183
    }
slouken@0
   184
slouken@1895
   185
    /* Set up the blit operation */
slouken@1895
   186
    if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
slouken@1895
   187
        Uint32 colorkey;
slouken@0
   188
slouken@1895
   189
        blitop = MGADWG_BFCOL | MGADWG_BITBLT |
slouken@1895
   190
            MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16) | MGADWG_TRANSC;
slouken@0
   191
slouken@1895
   192
        colorkey = src->format->colorkey;
slouken@1895
   193
        switch (dst->format->BytesPerPixel) {
slouken@1895
   194
        case 1:
slouken@1895
   195
            colorkey |= (colorkey << 8);
slouken@1895
   196
        case 2:
slouken@1895
   197
            colorkey |= (colorkey << 16);
slouken@1895
   198
            break;
slouken@1895
   199
        }
slouken@1895
   200
        mga_wait(2);
slouken@1895
   201
        mga_out32(MGAREG_FCOL, colorkey);
slouken@1895
   202
        mga_out32(MGAREG_BCOL, 0xFFFFFFFF);
slouken@1895
   203
    } else {
slouken@1895
   204
        blitop = MGADWG_BFCOL | MGADWG_BITBLT |
slouken@1895
   205
            MGADWG_SHIFTZERO | MGADWG_RSTR | (0x0C << 16);
slouken@1895
   206
    }
slouken@1895
   207
    mga_wait(7);
slouken@1895
   208
    mga_out32(MGAREG_SGN, sign);
slouken@1895
   209
    mga_out32(MGAREG_AR3, start);
slouken@1895
   210
    mga_out32(MGAREG_AR0, stop);
slouken@1895
   211
    mga_out32(MGAREG_AR5, skip);
slouken@1895
   212
    mga_out32(MGAREG_FXBNDRY, (dstX | ((dstX + w - 1) << 16)));
slouken@1895
   213
    mga_out32(MGAREG_YDSTLEN, (dstY << 16) | h);
slouken@1895
   214
    mga_out32(MGAREG_DWGCTL + MGAREG_EXEC, blitop);
slouken@0
   215
slouken@1895
   216
    FB_AddBusySurface(src);
slouken@1895
   217
    FB_AddBusySurface(dst);
slouken@106
   218
slouken@1895
   219
    if (dst == this->screen) {
slouken@1895
   220
        SDL_mutexV(hw_lock);
slouken@1895
   221
    }
slouken@1895
   222
    return (0);
slouken@0
   223
}
slouken@0
   224
slouken@1895
   225
static int
slouken@1895
   226
CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
slouken@0
   227
{
slouken@1895
   228
    int accelerated;
slouken@0
   229
slouken@1895
   230
    /* Set initial acceleration on */
slouken@1895
   231
    src->flags |= SDL_HWACCEL;
slouken@0
   232
slouken@1895
   233
    /* Set the surface attributes */
slouken@1895
   234
    if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) {
slouken@1895
   235
        if (!this->info.blit_hw_A) {
slouken@1895
   236
            src->flags &= ~SDL_HWACCEL;
slouken@1895
   237
        }
slouken@1895
   238
    }
slouken@1895
   239
    if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) {
slouken@1895
   240
        if (!this->info.blit_hw_CC) {
slouken@1895
   241
            src->flags &= ~SDL_HWACCEL;
slouken@1895
   242
        }
slouken@1895
   243
    }
slouken@0
   244
slouken@1895
   245
    /* Check to see if final surface blit is accelerated */
slouken@1895
   246
    accelerated = !!(src->flags & SDL_HWACCEL);
slouken@1895
   247
    if (accelerated) {
slouken@1895
   248
        src->map->hw_blit = HWAccelBlit;
slouken@1895
   249
    }
slouken@1895
   250
    return (accelerated);
slouken@0
   251
}
slouken@0
   252
slouken@1895
   253
void
slouken@1895
   254
FB_MatroxAccel(_THIS, __u32 card)
slouken@0
   255
{
slouken@1895
   256
    /* We have hardware accelerated surface functions */
slouken@1895
   257
    this->CheckHWBlit = CheckHWBlit;
slouken@1895
   258
    wait_vbl = WaitVBL;
slouken@1895
   259
    wait_idle = WaitIdle;
slouken@0
   260
slouken@1895
   261
    /* The Matrox has an accelerated color fill */
slouken@1895
   262
    this->info.blit_fill = 1;
slouken@1895
   263
    this->FillHWRect = FillHWRect;
slouken@0
   264
slouken@1895
   265
    /* The Matrox has accelerated normal and colorkey blits. */
slouken@1895
   266
    this->info.blit_hw = 1;
slouken@1895
   267
    /* The Millenium I appears to do the colorkey test a word
slouken@1895
   268
       at a time, and the transparency is intverted. (?)
slouken@1895
   269
     */
slouken@1895
   270
    if (card != FB_ACCEL_MATROX_MGA2064W) {
slouken@1895
   271
        this->info.blit_hw_CC = 1;
slouken@1895
   272
        this->SetHWColorKey = SetHWColorKey;
slouken@1895
   273
    }
slouken@1895
   274
#if 0                           /* Not yet implemented? */
slouken@1895
   275
    /* The Matrox G200/G400 has an accelerated alpha blit */
slouken@1895
   276
    if ((card == FB_ACCEL_MATROX_MGAG200)
slouken@1895
   277
        || (card == FB_ACCEL_MATROX_MGAG400)) {
slouken@1895
   278
        this->info.blit_hw_A = 1;
slouken@1895
   279
        this->SetHWAlpha = SetHWAlpha;
slouken@1895
   280
    }
slouken@0
   281
#endif
slouken@0
   282
}
slouken@1895
   283
slouken@1895
   284
/* vi: set ts=4 sw=4 expandtab: */