src/video/nds/SDL_ndsrender.c
author Darren Alton <dalton@stevens.edu>
Wed, 02 Jul 2008 13:59:30 +0000
branchgsoc2008_nds
changeset 2677 6386764eb222
parent 2673 24a6b3588eac
child 2678 3895761db26a
permissions -rw-r--r--
Starting to work on a more complete video driver.
dalton@2670
     1
/*
dalton@2670
     2
    SDL - Simple DirectMedia Layer
dalton@2670
     3
    Copyright (C) 1997-2006 Sam Lantinga
dalton@2670
     4
dalton@2670
     5
    This library is free software; you can redistribute it and/or
dalton@2670
     6
    modify it under the terms of the GNU Lesser General Public
dalton@2670
     7
    License as published by the Free Software Foundation; either
dalton@2670
     8
    version 2.1 of the License, or (at your option) any later version.
dalton@2670
     9
dalton@2670
    10
    This library is distributed in the hope that it will be useful,
dalton@2670
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
dalton@2670
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dalton@2670
    13
    Lesser General Public License for more details.
dalton@2670
    14
dalton@2670
    15
    You should have received a copy of the GNU Lesser General Public
dalton@2670
    16
    License along with this library; if not, write to the Free Software
dalton@2670
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
dalton@2670
    18
dalton@2670
    19
    Sam Lantinga
dalton@2670
    20
    slouken@libsdl.org
dalton@2670
    21
*/
dalton@2670
    22
dalton@2670
    23
#include <stdio.h>
dalton@2670
    24
#include <stdlib.h>
dalton@2670
    25
#include <nds.h>
dalton@2670
    26
dalton@2670
    27
#include "SDL_config.h"
dalton@2670
    28
dalton@2670
    29
#include "SDL_video.h"
dalton@2670
    30
#include "../SDL_sysvideo.h"
dalton@2670
    31
#include "../SDL_yuv_sw_c.h"
dalton@2670
    32
#include "../SDL_renderer_sw.h"
dalton@2670
    33
dalton@2670
    34
dalton@2670
    35
/* SDL surface based renderer implementation */
dalton@2670
    36
dalton@2677
    37
static SDL_Renderer *NDS_CreateRenderer(SDL_Window * window, Uint32 flags);
dalton@2677
    38
static int NDS_ActivateRenderer(SDL_Renderer * renderer);
dalton@2677
    39
static int NDS_DisplayModeChanged(SDL_Renderer * renderer);
dalton@2677
    40
static int NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dalton@2677
    41
static int NDS_QueryTexturePixels(SDL_Renderer * renderer,
dalton@2677
    42
                                 SDL_Texture * texture, void **pixels,
dalton@2677
    43
                                 int *pitch);
dalton@2677
    44
static int NDS_SetTexturePalette(SDL_Renderer * renderer,
dalton@2677
    45
                                SDL_Texture * texture,
dalton@2677
    46
                                const SDL_Color * colors, int firstcolor,
dalton@2677
    47
                                int ncolors);
dalton@2677
    48
static int NDS_GetTexturePalette(SDL_Renderer * renderer,
dalton@2677
    49
                                SDL_Texture * texture, SDL_Color * colors,
dalton@2677
    50
                                int firstcolor, int ncolors);
dalton@2677
    51
static int NDS_SetTextureColorMod(SDL_Renderer * renderer,
dalton@2677
    52
                                 SDL_Texture * texture);
dalton@2677
    53
static int NDS_SetTextureAlphaMod(SDL_Renderer * renderer,
dalton@2677
    54
                                 SDL_Texture * texture);
dalton@2677
    55
static int NDS_SetTextureBlendMode(SDL_Renderer * renderer,
dalton@2677
    56
                                  SDL_Texture * texture);
dalton@2677
    57
static int NDS_SetTextureScaleMode(SDL_Renderer * renderer,
dalton@2677
    58
                                  SDL_Texture * texture);
dalton@2677
    59
static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2677
    60
                            const SDL_Rect * rect, const void *pixels,
dalton@2677
    61
                            int pitch);
dalton@2677
    62
static int NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2677
    63
                          const SDL_Rect * rect, int markDirty, void **pixels,
dalton@2677
    64
                          int *pitch);
dalton@2677
    65
static void NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dalton@2677
    66
static void NDS_DirtyTexture(SDL_Renderer * renderer,
dalton@2677
    67
                            SDL_Texture * texture, int numrects,
dalton@2677
    68
                            const SDL_Rect * rects);
dalton@2677
    69
static int NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
dalton@2671
    70
                              Uint8 b, Uint8 a, const SDL_Rect * rect);
dalton@2677
    71
static int NDS_RenderCopy(SDL_Renderer * renderer,
dalton@2671
    72
                              SDL_Texture * texture,
dalton@2671
    73
                              const SDL_Rect * srcrect,
dalton@2671
    74
                              const SDL_Rect * dstrect);
dalton@2677
    75
static void NDS_RenderPresent(SDL_Renderer * renderer);
dalton@2677
    76
static void NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
dalton@2677
    77
static void NDS_DestroyRenderer(SDL_Renderer * renderer);
dalton@2670
    78
dalton@2670
    79
dalton@2677
    80
SDL_RenderDriver NDS_RenderDriver = {
dalton@2677
    81
    NDS_CreateRenderer,
dalton@2671
    82
    {"nds", SDL_RENDERER_PRESENTCOPY}
dalton@2670
    83
/*   (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
dalton@2670
    84
      SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
dalton@2670
    85
      SDL_RENDERER_PRESENTDISCARD),*/
dalton@2670
    86
};
dalton@2670
    87
dalton@2670
    88
typedef struct
dalton@2670
    89
{
dalton@2670
    90
    int current_screen;
dalton@2677
    91
    u16* fb;
dalton@2677
    92
} NDS_RenderData;
dalton@2670
    93
dalton@2672
    94
dalton@2672
    95
dalton@2672
    96
/* this is mainly hackish testing/debugging stuff to get cleaned up soon
dalton@2672
    97
   anything named sdlds_blah shouldn't make it into the stable version
dalton@2672
    98
 */
dalton@2672
    99
dalton@2672
   100
u16
dalton@2673
   101
sdlds_rgb2bgr(u16 c)
dalton@2673
   102
{
dalton@2673
   103
/* hack to get the proper colors until I actually get BGR555 to work right */
dalton@2672
   104
    u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b;
dalton@2672
   105
    r = (c & Rmask) >> 10;
dalton@2672
   106
    b = (c & Bmask) << 10;
dalton@2672
   107
    return (c & GAmask) | r | b;
dalton@2672
   108
}
dalton@2672
   109
dalton@2672
   110
void
dalton@2672
   111
sdlds_surf2vram(SDL_Surface * s)
dalton@2672
   112
{
dalton@2673
   113
    if (s->w == 256) {
dalton@2677
   114
        u16 tmpbuf[0x20000];
dalton@2677
   115
        int i;
dalton@2677
   116
dalton@2673
   117
        dmaCopy((u8 *) (s->pixels) + 156 * sizeof(u16),
dalton@2677
   118
                tmpbuf, 256 * 192 * sizeof(u16));
dalton@2677
   119
    /* hack to fix the pixel format until I figure out why BGR doesn't work */
dalton@2677
   120
        for (i = 0; i < 256 * 192; ++i) {
dalton@2677
   121
            tmpbuf[i] = sdlds_rgb2bgr(tmpbuf[i]);
dalton@2677
   122
        }
dalton@2677
   123
        dmaCopy(tmpbuf, VRAM_A, 256 * 192 * sizeof(u16));
dalton@2672
   124
    }
dalton@2672
   125
}
dalton@2672
   126
dalton@2672
   127
void
dalton@2673
   128
sdlds_print_pixfmt_info(SDL_PixelFormat * f)
dalton@2673
   129
{
dalton@2673
   130
    if (!f)
dalton@2673
   131
        return;
dalton@2673
   132
    printf("bpp: %d\nRGBA: %x %x %x %x\n",
dalton@2673
   133
           f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
dalton@2672
   134
}
dalton@2672
   135
dalton@2672
   136
void
dalton@2673
   137
sdlds_print_surface_info(SDL_Surface * s)
dalton@2673
   138
{
dalton@2673
   139
    if (!s)
dalton@2673
   140
        return;
dalton@2673
   141
    printf("flags: %x\nsize: %dx%d, pitch: %d\nlocked: %d, refcount: %d\n",
dalton@2673
   142
           s->flags, s->w, s->h, s->pitch, s->locked, s->refcount);
dalton@2673
   143
    sdlds_print_pixfmt_info(s->format);
dalton@2672
   144
}
dalton@2672
   145
dalton@2672
   146
dalton@2672
   147
dalton@2670
   148
SDL_Renderer *
dalton@2677
   149
NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
dalton@2670
   150
{
dalton@2670
   151
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
dalton@2670
   152
    SDL_DisplayMode *displayMode = &display->current_mode;
dalton@2670
   153
    SDL_Renderer *renderer;
dalton@2677
   154
    NDS_RenderData *data;
dalton@2670
   155
    int i, n;
dalton@2672
   156
    int bpp = 15;
dalton@2673
   157
    Uint32 Rmask, Gmask, Bmask, Amask;
dalton@2673
   158
/*  Uint32 Rmask = 0x7C00, Gmask = 0x03E0, Bmask = 0x001F, Amask = 0x8000;
dalton@2672
   159
    Uint32 Rmask = 0x001F, Gmask = 0x03E0, Bmask = 0x7C00, Amask = 0x8000;
dalton@2673
   160
*/
dalton@2670
   161
dalton@2673
   162
    /* hard coded this to BGR555 for now */
dalton@2673
   163
    if (!SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_BGR555, &bpp,
dalton@2673
   164
                                    &Rmask, &Gmask, &Bmask, &Amask)) {
dalton@2673
   165
        SDL_SetError("Unknown display format");
dalton@2673
   166
        return NULL;
dalton@2673
   167
    }
dalton@2670
   168
dalton@2670
   169
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
dalton@2670
   170
    if (!renderer) {
dalton@2670
   171
        SDL_OutOfMemory();
dalton@2670
   172
        return NULL;
dalton@2670
   173
    }
dalton@2670
   174
dalton@2677
   175
    data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
dalton@2670
   176
    if (!data) {
dalton@2677
   177
        NDS_DestroyRenderer(renderer);
dalton@2670
   178
        SDL_OutOfMemory();
dalton@2670
   179
        return NULL;
dalton@2670
   180
    }
dalton@2670
   181
    SDL_zerop(data);
dalton@2670
   182
dalton@2677
   183
    renderer->RenderFill = NDS_RenderFill;
dalton@2677
   184
    renderer->RenderCopy = NDS_RenderCopy;
dalton@2677
   185
    renderer->RenderPresent = NDS_RenderPresent;
dalton@2677
   186
    renderer->DestroyRenderer = NDS_DestroyRenderer;
dalton@2677
   187
    renderer->info.name = NDS_RenderDriver.info.name;
dalton@2670
   188
    renderer->info.flags = 0;
dalton@2670
   189
    renderer->window = window->id;
dalton@2670
   190
    renderer->driverdata = data;
dalton@2677
   191
    Setup_SoftwareRenderer(renderer); /* TODO: well, "TODON'T" is more like it */
dalton@2670
   192
dalton@2670
   193
    if (flags & SDL_RENDERER_PRESENTFLIP2) {
dalton@2670
   194
        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
dalton@2670
   195
        n = 2;
dalton@2670
   196
    } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
dalton@2670
   197
        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
dalton@2670
   198
        n = 3;
dalton@2670
   199
    } else {
dalton@2670
   200
        renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
dalton@2670
   201
        n = 1;
dalton@2677
   202
    }/*
dalton@2670
   203
    for (i = 0; i < n; ++i) {
dalton@2670
   204
        data->screens[i] =
dalton@2673
   205
            SDL_CreateRGBSurface(0, 256, 192, bpp, Rmask, Gmask, Bmask,
dalton@2673
   206
                                 Amask);
dalton@2670
   207
        if (!data->screens[i]) {
dalton@2677
   208
            NDS_DestroyRenderer(renderer);
dalton@2670
   209
            return NULL;
dalton@2670
   210
        }
dalton@2670
   211
        SDL_SetSurfacePalette(data->screens[i], display->palette);
dalton@2673
   212
        sdlds_print_surface_info(data->screens[i]);
dalton@2677
   213
    }*/
dalton@2670
   214
dalton@2677
   215
    data->fb = (u16*)0x06020000;
dalton@2672
   216
dalton@2670
   217
    return renderer;
dalton@2670
   218
}
dalton@2670
   219
dalton@2670
   220
static int
dalton@2677
   221
NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
dalton@2671
   222
                   Uint8 a, const SDL_Rect * rect)
dalton@2670
   223
{
dalton@2677
   224
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2670
   225
    SDL_Rect real_rect = *rect;
dalton@2677
   226
    u16 color;
dalton@2677
   227
    int i, j;
dalton@2670
   228
dalton@2677
   229
    color = RGB15(r>>3,g>>3,b>>3);
dalton@2677
   230
    for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) {
dalton@2677
   231
        for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) {
dalton@2677
   232
            data->fb[(j + real_rect.y) * 256 + i + real_rect.x] = 
dalton@2677
   233
                0x8000 | color;
dalton@2677
   234
        }
dalton@2677
   235
    }
dalton@2677
   236
    return 0;
dalton@2670
   237
}
dalton@2670
   238
static int
dalton@2677
   239
NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
dalton@2671
   240
                   const SDL_Rect * srcrect, const SDL_Rect * dstrect)
dalton@2670
   241
{
dalton@2677
   242
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2670
   243
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
dalton@2670
   244
    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
dalton@2677
   245
dalton@2672
   246
#if 0
dalton@2670
   247
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
dalton@2670
   248
        SDL_Surface *target = data->screens[data->current_screen];
dalton@2670
   249
        void *pixels =
dalton@2670
   250
            (Uint8 *) target->pixels + dstrect->y * target->pitch +
dalton@2670
   251
            dstrect->x * target->format->BytesPerPixel;
dalton@2670
   252
        return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
dalton@2670
   253
                                   srcrect, display->current_mode.format,
dalton@2670
   254
                                   dstrect->w, dstrect->h, pixels,
dalton@2670
   255
                                   target->pitch);
dalton@2670
   256
    } else {
dalton@2670
   257
        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
dalton@2670
   258
        SDL_Surface *target = data->screens[data->current_screen];
dalton@2670
   259
        SDL_Rect real_srcrect = *srcrect;
dalton@2670
   260
        SDL_Rect real_dstrect = *dstrect;
dalton@2672
   261
        /*sdlds_print_surface_info(surface);
dalton@2673
   262
           sdlds_print_surface_info(target); */
dalton@2670
   263
        sdlds_surf2vram(surface);
dalton@2670
   264
        return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
dalton@2670
   265
    }
dalton@2677
   266
#endif
dalton@2672
   267
    /* copy it directly to vram */
dalton@2671
   268
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
dalton@2677
   269
    sdlds_surf2vram(surface);
dalton@2677
   270
    /*
dalton@2671
   271
    int sx = srcrect->x, sy = srcrect->y, sw = srcrect->w, sh = srcrect->h;
dalton@2671
   272
    int dx = dstrect->x, dy = dstrect->y, dw = dstrect->w, dh = dstrect->h;
dalton@2671
   273
    int si, sj, di, dj;
dalton@2671
   274
    for (sj = 0, dj = 0; sj < sh && dj < dh; ++sj, ++dj) {
dalton@2671
   275
        for (si = 0, di = 0; si < sw && di < dw; ++si, ++di) {
dalton@2677
   276
            data->fb[(dj + dy) * 256 + di + dx] = 0x8000 |
dalton@2677
   277
                ((u16 *) surface->pixels)[(sj + sy) * (surface->w) + si +
dalton@2673
   278
                                             sx];
dalton@2670
   279
        }
dalton@2677
   280
    }*/
dalton@2672
   281
    return 0;
dalton@2671
   282
}
dalton@2671
   283
dalton@2670
   284
dalton@2670
   285
static void
dalton@2677
   286
NDS_RenderPresent(SDL_Renderer * renderer)
dalton@2670
   287
{
dalton@2677
   288
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2677
   289
    /* Send the data to the display TODO */
dalton@2670
   290
dalton@2670
   291
    /* Update the flipping chain, if any */
dalton@2670
   292
    if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
dalton@2670
   293
        data->current_screen = (data->current_screen + 1) % 2;
dalton@2670
   294
    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
dalton@2670
   295
        data->current_screen = (data->current_screen + 1) % 3;
dalton@2670
   296
    }
dalton@2670
   297
}
dalton@2670
   298
dalton@2670
   299
static void
dalton@2677
   300
NDS_DestroyRenderer(SDL_Renderer * renderer)
dalton@2670
   301
{
dalton@2677
   302
    NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
dalton@2670
   303
    int i;
dalton@2670
   304
dalton@2677
   305
    printf("NDS_DestroyRenderer(renderer)\n");
dalton@2670
   306
    printf(" renderer: %s\n", renderer->info.name);
dalton@2670
   307
    if (data) {
dalton@2677
   308
        /*for (i = 0; i < SDL_arraysize(data->screens); ++i) {
dalton@2670
   309
            if (data->screens[i]) {
dalton@2670
   310
                SDL_FreeSurface(data->screens[i]);
dalton@2670
   311
            }
dalton@2677
   312
        }*/
dalton@2670
   313
        SDL_free(data);
dalton@2670
   314
    }
dalton@2670
   315
    SDL_free(renderer);
dalton@2670
   316
}
dalton@2670
   317
dalton@2670
   318
/* vi: set ts=4 sw=4 expandtab: */