src/video/nds/SDL_ndsrender.c
author Darren Alton <dalton@stevens.edu>
Sun, 13 Jul 2008 04:28:54 +0000
branchgsoc2008_nds
changeset 2679 bc3e3e889f6d
parent 2678 3895761db26a
child 2680 4135aa9c5645
permissions -rw-r--r--
More NDS video driver work.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #include <stdio.h>
    24 #include <stdlib.h>
    25 #include <nds.h>
    26 
    27 #include "SDL_config.h"
    28 
    29 #include "SDL_video.h"
    30 #include "../SDL_sysvideo.h"
    31 #include "../SDL_yuv_sw_c.h"
    32 #include "../SDL_renderer_sw.h"
    33 
    34 
    35 /* SDL surface based renderer implementation */
    36 
    37 static SDL_Renderer *NDS_CreateRenderer(SDL_Window * window, Uint32 flags);
    38 static int NDS_ActivateRenderer(SDL_Renderer * renderer);
    39 static int NDS_DisplayModeChanged(SDL_Renderer * renderer);
    40 static int NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    41 static int NDS_QueryTexturePixels(SDL_Renderer * renderer,
    42                                  SDL_Texture * texture, void **pixels,
    43                                  int *pitch);
    44 static int NDS_SetTexturePalette(SDL_Renderer * renderer,
    45                                 SDL_Texture * texture,
    46                                 const SDL_Color * colors, int firstcolor,
    47                                 int ncolors);
    48 static int NDS_GetTexturePalette(SDL_Renderer * renderer,
    49                                 SDL_Texture * texture, SDL_Color * colors,
    50                                 int firstcolor, int ncolors);
    51 static int NDS_SetTextureColorMod(SDL_Renderer * renderer,
    52                                  SDL_Texture * texture);
    53 static int NDS_SetTextureAlphaMod(SDL_Renderer * renderer,
    54                                  SDL_Texture * texture);
    55 static int NDS_SetTextureBlendMode(SDL_Renderer * renderer,
    56                                   SDL_Texture * texture);
    57 static int NDS_SetTextureScaleMode(SDL_Renderer * renderer,
    58                                   SDL_Texture * texture);
    59 static int NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    60                             const SDL_Rect * rect, const void *pixels,
    61                             int pitch);
    62 static int NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
    63                           const SDL_Rect * rect, int markDirty, void **pixels,
    64                           int *pitch);
    65 static void NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    66 static void NDS_DirtyTexture(SDL_Renderer * renderer,
    67                             SDL_Texture * texture, int numrects,
    68                             const SDL_Rect * rects);
    69 static int NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
    70                               Uint8 b, Uint8 a, const SDL_Rect * rect);
    71 static int NDS_RenderCopy(SDL_Renderer * renderer,
    72                               SDL_Texture * texture,
    73                               const SDL_Rect * srcrect,
    74                               const SDL_Rect * dstrect);
    75 static void NDS_RenderPresent(SDL_Renderer * renderer);
    76 static void NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
    77 static void NDS_DestroyRenderer(SDL_Renderer * renderer);
    78 
    79 
    80 SDL_RenderDriver NDS_RenderDriver = {
    81     NDS_CreateRenderer,
    82     {   "nds", /* char* name */
    83         (SDL_RENDERER_SINGLEBUFFER|SDL_RENDERER_ACCELERATED), /* u32 flags */
    84         (SDL_TEXTUREMODULATE_NONE), /* u32 mod_modes */
    85         (SDL_TEXTUREBLENDMODE_NONE), /* u32 blend_modes */
    86         (SDL_TEXTURESCALEMODE_NONE), /* u32 scale_modes */
    87         3, /* u32 num_texture_formats */
    88         {
    89             SDL_PIXELFORMAT_INDEX8,
    90             SDL_PIXELFORMAT_RGB555,
    91             SDL_PIXELFORMAT_RGB565
    92         }, /* u32 texture_formats[20] */
    93         (256), /* int max_texture_width */
    94         (256), /* int max_texture_height */
    95     }
    96 };
    97 
    98 typedef struct
    99 {
   100     bg_attribute *bg;
   101     u8 bg_taken[4];
   102     int sub;
   103 } NDS_RenderData;
   104 
   105 typedef struct
   106 {
   107     enum { NDSTX_BG, NDSTX_SPR } type;
   108     int hw_index;
   109     struct { int w, h, pitch, bpp; } dim;
   110     u16 *vram;
   111 } NDS_TextureData;
   112 
   113 
   114 /* this is mainly hackish testing/debugging stuff to get cleaned up soon
   115    anything named sdlds_blah shouldn't make it into the stable version
   116  */
   117 
   118 u16
   119 sdlds_rgb2bgr(u16 c)
   120 {
   121 /* hack to get the proper colors until I actually get BGR555 to work right */
   122     u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b;
   123     r = (c & Rmask) >> 10;
   124     b = (c & Bmask) << 10;
   125     return (c & GAmask) | r | b;
   126 }
   127 
   128 void
   129 sdlds_print_pixfmt_info(SDL_PixelFormat * f)
   130 {
   131     if (!f)
   132         return;
   133     printf("bpp: %d\nRGBA: %x %x %x %x\n",
   134            f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
   135 }
   136 
   137 void
   138 sdlds_print_surface_info(SDL_Surface * s)
   139 {
   140     if (!s)
   141         return;
   142     printf("flags: %x\nsize: %dx%d, pitch: %d\nlocked: %d, refcount: %d\n",
   143            s->flags, s->w, s->h, s->pitch, s->locked, s->refcount);
   144     sdlds_print_pixfmt_info(s->format);
   145 }
   146 
   147 /* again the above shouldn't make it into the stable version */
   148 
   149 SDL_Renderer *
   150 NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
   151 {
   152     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   153     SDL_DisplayMode *displayMode = &display->current_mode;
   154     SDL_Renderer *renderer;
   155     NDS_RenderData *data;
   156     int i, n;
   157     int bpp = 15;
   158     Uint32 Rmask, Gmask, Bmask, Amask;
   159 /*  Uint32 Rmask = 0x7C00, Gmask = 0x03E0, Bmask = 0x001F, Amask = 0x8000;
   160     Uint32 Rmask = 0x001F, Gmask = 0x03E0, Bmask = 0x7C00, Amask = 0x8000;
   161 */
   162 
   163     /* hard coded this to BGR555 for now */
   164     if (!SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_BGR555, &bpp,
   165                                     &Rmask, &Gmask, &Bmask, &Amask)) {
   166         SDL_SetError("Unknown display format");
   167         return NULL;
   168     }
   169 
   170     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   171     if (!renderer) {
   172         SDL_OutOfMemory();
   173         return NULL;
   174     }
   175 
   176     data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
   177     if (!data) {
   178         NDS_DestroyRenderer(renderer);
   179         SDL_OutOfMemory();
   180         return NULL;
   181     }
   182     SDL_zerop(data);
   183 
   184     renderer->RenderFill = NDS_RenderFill;
   185     renderer->RenderCopy = NDS_RenderCopy;
   186     renderer->RenderPresent = NDS_RenderPresent;
   187     renderer->DestroyRenderer = NDS_DestroyRenderer;
   188     renderer->info.name = NDS_RenderDriver.info.name;
   189     renderer->info.flags = 0;
   190     renderer->window = window->id;
   191     renderer->driverdata = data;
   192     renderer->CreateTexture = NDS_CreateTexture;
   193     renderer->QueryTexturePixels = NDS_QueryTexturePixels;
   194     renderer->SetTexturePalette = NDS_SetTexturePalette;
   195     renderer->GetTexturePalette = NDS_GetTexturePalette;
   196     renderer->SetTextureColorMod = NDS_SetTextureColorMod;
   197     renderer->SetTextureAlphaMod = NDS_SetTextureAlphaMod;
   198     renderer->SetTextureBlendMode = NDS_SetTextureBlendMode;
   199     renderer->SetTextureScaleMode = NDS_SetTextureScaleMode;
   200     renderer->UpdateTexture = NDS_UpdateTexture;
   201     renderer->LockTexture = NDS_LockTexture;
   202     renderer->UnlockTexture = NDS_UnlockTexture;
   203     renderer->DirtyTexture = NDS_DirtyTexture;
   204     renderer->DestroyTexture = NDS_DestroyTexture;
   205 
   206     renderer->info.mod_modes = NDS_RenderDriver.info.mod_modes;
   207     renderer->info.blend_modes = NDS_RenderDriver.info.blend_modes;
   208     renderer->info.scale_modes = NDS_RenderDriver.info.scale_modes;
   209     renderer->info.num_texture_formats =
   210         NDS_RenderDriver.info.num_texture_formats;
   211     SDL_memcpy(renderer->info.texture_formats,
   212                NDS_RenderDriver.info.texture_formats,
   213                sizeof(renderer->info.texture_formats));;
   214     renderer->info.max_texture_width = NDS_RenderDriver.info.max_texture_width;
   215     renderer->info.max_texture_height =
   216         NDS_RenderDriver.info.max_texture_height;
   217 
   218     /*data->fb = (u16*)0x06020000;*/
   219     data->bg = &BACKGROUND;
   220     data->bg_taken[2] = data->bg_taken[3] = 0;
   221     data->sub = 0;
   222 
   223     return renderer;
   224 }
   225 
   226 static int
   227 NDS_ActivateRenderer(SDL_Renderer * renderer)
   228 {
   229     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   230     /* stub. TODO: figure out what needs to be done, if anything. */
   231     return 0;
   232 }
   233 
   234 static int
   235 NDS_DisplayModeChanged(SDL_Renderer * renderer)
   236 {
   237     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   238     /* stub. TODO: figure out what needs to be done */
   239     return 0;
   240 }
   241 
   242 static int
   243 NDS_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   244 {
   245     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   246     NDS_TextureData *txdat = NULL;
   247     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   248         SDL_SetError("Unsupported texture format");
   249         return -1;
   250     } else {
   251         int bpp;
   252         Uint32 Rmask, Gmask, Bmask, Amask;
   253 
   254         if (!SDL_PixelFormatEnumToMasks
   255             (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   256             SDL_SetError("Unknown texture format");
   257             return -1;
   258         }
   259         /* conditional statements on w/h to place it as bg/sprite */
   260         /*if(texture->w <= 64 && texture->h <= 64) {
   261             sprites not implemented yet.  elegant, I know.
   262         } else*/ if(texture->w <= 256 && texture->h <= 256) {
   263             int whichbg = -1;
   264             if(!data->bg_taken[2]) {
   265                 whichbg = 2;
   266                 data->bg->bg2_rotation.xdx = 0x100;
   267                 data->bg->bg2_rotation.xdy = 0;
   268                 data->bg->bg2_rotation.ydx = 0;
   269                 data->bg->bg2_rotation.ydy = 0x100;
   270                 data->bg->bg2_rotation.centerX = 0;
   271                 data->bg->bg2_rotation.centerY = 0;
   272             } else if(!data->bg_taken[3]) {
   273                 whichbg = 3;
   274                 data->bg->bg3_rotation.xdx = 0x100;
   275                 data->bg->bg3_rotation.xdy = 0;
   276                 data->bg->bg3_rotation.ydx = 0;
   277                 data->bg->bg3_rotation.ydy = 0x100;
   278                 data->bg->bg3_rotation.centerX = 0;
   279                 data->bg->bg3_rotation.centerY = 0;
   280             }
   281             if(whichbg >= 0) {
   282                 data->bg->control[whichbg] = (bpp == 8) ?
   283                     BG_BMP8_256x256 : BG_BMP16_256x256;
   284                 data->bg->scroll[whichbg].x = 0;
   285                 data->bg->scroll[whichbg].y = 0;
   286                 texture->driverdata = SDL_calloc(1, sizeof(NDS_TextureData));
   287                 txdat = (NDS_TextureData*)texture->driverdata;
   288                 txdat->type = NDSTX_BG;
   289                 txdat->hw_index = whichbg;
   290                 txdat->dim.w = texture->w;
   291                 txdat->dim.h = texture->h;
   292                 txdat->dim.pitch = 256 * (bpp/8);
   293                 txdat->dim.bpp = bpp;
   294                 txdat->vram = (u16*)(data->sub ?
   295                     BG_BMP_RAM_SUB(whichbg) : BG_BMP_RAM(whichbg));
   296             } else {
   297                 SDL_SetError("Out of NDS backgrounds.");
   298             }
   299         } else {
   300             SDL_SetError("Texture too big for NDS hardware.");
   301         }
   302     }
   303 
   304     if (!texture->driverdata) {
   305         return -1;
   306     }
   307     return 0;
   308 }
   309 
   310 static int
   311 NDS_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
   312                       void **pixels, int *pitch)
   313 {
   314     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   315         SDL_SetError("Unsupported texture format");
   316         return -1;
   317     } else {
   318         NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   319 
   320         *pixels = txdat->vram;
   321         *pitch = txdat->dim.pitch;
   322         return 0;
   323     }
   324 }
   325 
   326 static int
   327 NDS_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   328                      const SDL_Color * colors, int firstcolor, int ncolors)
   329 {
   330     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   331         SDL_SetError("YUV textures don't have a palette");
   332         return -1;
   333     } else {
   334         NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   335         /* TODO: mess with 8-bit modes and/or 16-color palette modes */
   336         return 0;
   337     }
   338 }
   339 
   340 static int
   341 NDS_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
   342                      SDL_Color * colors, int firstcolor, int ncolors)
   343 {
   344     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   345         SDL_SetError("YUV textures don't have a palette");
   346         return -1;
   347     } else {
   348         NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   349         /* TODO: mess with 8-bit modes and/or 16-color palette modes */
   350         return 0;
   351     }
   352 }
   353 
   354 static int
   355 NDS_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
   356 {
   357     /* stub. TODO: figure out what needs to be done, if anything */
   358     return 0;
   359 }
   360 
   361 static int
   362 NDS_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
   363 {
   364     /* stub. TODO: figure out what needs to be done, if anything */
   365     return 0;
   366 }
   367 
   368 static int
   369 NDS_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
   370 {
   371     /* stub. TODO: figure out what needs to be done, if anything */
   372     return 0;
   373 }
   374 
   375 static int
   376 NDS_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
   377 {
   378     /* stub. TODO: figure out what needs to be done.
   379        (NDS hardware scaling is nearest neighbor.) */
   380     return 0;
   381 }
   382 
   383 static int
   384 NDS_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   385                  const SDL_Rect * rect, const void *pixels, int pitch)
   386 {
   387     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   388         SDL_SetError("Unsupported texture format");
   389         return -1;
   390     } else {
   391         NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   392         Uint8 *src, *dst;
   393         int row;
   394         size_t length;
   395         /* IMPORTANT! copy the new pixels into the sprite or bg. */
   396         src = (Uint8 *) pixels;
   397         dst =
   398             (Uint8 *) txdat->vram + rect->y * txdat->dim.pitch +
   399             rect->x * (txdat->dim.bpp/8);
   400         length = rect->w * (txdat->dim.bpp/8);
   401         for (row = 0; row < rect->h; ++row) {
   402             SDL_memcpy(dst, src, length);
   403             src += pitch;
   404             dst += txdat->dim.pitch;
   405         }
   406         return 0;
   407     }
   408 }
   409 
   410 static int
   411 NDS_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   412                const SDL_Rect * rect, int markDirty, void **pixels,
   413                int *pitch)
   414 {
   415     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   416         SDL_SetError("Unsupported texture format");
   417         return -1;
   418     } else {
   419         NDS_TextureData *txdat = (NDS_TextureData *) texture->driverdata;
   420 
   421         *pixels = (void *) ((u8 *)txdat->vram + rect->y * txdat->dim.pitch
   422                             + rect->x * (txdat->dim.bpp/8));
   423         *pitch = txdat->dim.pitch;
   424         return 0;
   425     }
   426 }
   427 
   428 static void
   429 NDS_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   430 {
   431     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   432         SDL_SetError("Unsupported texture format");
   433     }
   434 }
   435 
   436 static void
   437 NDS_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
   438                 int numrects, const SDL_Rect * rects)
   439 { /* stub */
   440 }
   441 
   442 static int
   443 NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
   444                    Uint8 a, const SDL_Rect * rect)
   445 {
   446     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   447     SDL_Rect real_rect = *rect;
   448     u16 color;
   449     int i, j;
   450 
   451     /* TODO: make a single-color sprite and stretch it.
   452     color = RGB15(r>>3,g>>3,b>>3);
   453     for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) {
   454         for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) {
   455             data->fb[(j + real_rect.y) * 256 + i + real_rect.x] = 
   456                 0x8000 | color;
   457         }
   458     }*/
   459     return 0;
   460 }
   461 
   462 static int
   463 NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   464                    const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   465 {
   466     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   467     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   468     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   469 
   470 #if 0
   471     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   472         SDL_Surface *target = data->screens[data->current_screen];
   473         void *pixels =
   474             (Uint8 *) target->pixels + dstrect->y * target->pitch +
   475             dstrect->x * target->format->BytesPerPixel;
   476         return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
   477                                    srcrect, display->current_mode.format,
   478                                    dstrect->w, dstrect->h, pixels,
   479                                    target->pitch);
   480     } else {
   481         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   482         SDL_Surface *target = data->screens[data->current_screen];
   483         SDL_Rect real_srcrect = *srcrect;
   484         SDL_Rect real_dstrect = *dstrect;
   485         return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
   486     }
   487 #endif
   488     return 0;
   489 }
   490 
   491 
   492 static void
   493 NDS_RenderPresent(SDL_Renderer * renderer)
   494 {
   495     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   496     /* Send the data to the display TODO */
   497 
   498     /* Update the flipping chain, if any */
   499     if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
   500         swiWaitForVBlank();
   501     }
   502 }
   503 
   504 static void
   505 NDS_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
   506 {
   507     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   508         SDL_SetError("Unsupported texture format");
   509     } else {
   510         /* free anything else allocated for texture */
   511         SDL_free(texture->driverdata);
   512     }
   513 }
   514 
   515 static void
   516 NDS_DestroyRenderer(SDL_Renderer * renderer)
   517 {
   518     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   519     /*SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   520     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);*/
   521     int i;
   522 
   523     if (data) {
   524         /* TODO: free anything relevant. */
   525         /*for (i = 0; i < SDL_arraysize(data->texture); ++i) {
   526             if (data->texture[i]) {
   527                 DestroyTexture(data->renderer, data->texture[i]);
   528             }
   529         }
   530         if (data->surface.format) {
   531             SDL_SetSurfacePalette(&data->surface, NULL);
   532             SDL_FreeFormat(data->surface.format);
   533         }
   534         if (display->palette) {
   535             SDL_DelPaletteWatch(display->palette, DisplayPaletteChanged,
   536                                 data);
   537         }
   538         SDL_FreeDirtyRects(&data->dirty);*/
   539         SDL_free(data);
   540     }
   541     SDL_free(renderer);
   542 }
   543 
   544 /* vi: set ts=4 sw=4 expandtab: */