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.
     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", SDL_RENDERER_PRESENTCOPY}
    83 /*   (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
    84       SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
    85       SDL_RENDERER_PRESENTDISCARD),*/
    86 };
    87 
    88 typedef struct
    89 {
    90     int current_screen;
    91     u16* fb;
    92 } NDS_RenderData;
    93 
    94 
    95 
    96 /* this is mainly hackish testing/debugging stuff to get cleaned up soon
    97    anything named sdlds_blah shouldn't make it into the stable version
    98  */
    99 
   100 u16
   101 sdlds_rgb2bgr(u16 c)
   102 {
   103 /* hack to get the proper colors until I actually get BGR555 to work right */
   104     u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b;
   105     r = (c & Rmask) >> 10;
   106     b = (c & Bmask) << 10;
   107     return (c & GAmask) | r | b;
   108 }
   109 
   110 void
   111 sdlds_surf2vram(SDL_Surface * s)
   112 {
   113     if (s->w == 256) {
   114         u16 tmpbuf[0x20000];
   115         int i;
   116 
   117         dmaCopy((u8 *) (s->pixels) + 156 * sizeof(u16),
   118                 tmpbuf, 256 * 192 * sizeof(u16));
   119     /* hack to fix the pixel format until I figure out why BGR doesn't work */
   120         for (i = 0; i < 256 * 192; ++i) {
   121             tmpbuf[i] = sdlds_rgb2bgr(tmpbuf[i]);
   122         }
   123         dmaCopy(tmpbuf, VRAM_A, 256 * 192 * sizeof(u16));
   124     }
   125 }
   126 
   127 void
   128 sdlds_print_pixfmt_info(SDL_PixelFormat * f)
   129 {
   130     if (!f)
   131         return;
   132     printf("bpp: %d\nRGBA: %x %x %x %x\n",
   133            f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
   134 }
   135 
   136 void
   137 sdlds_print_surface_info(SDL_Surface * s)
   138 {
   139     if (!s)
   140         return;
   141     printf("flags: %x\nsize: %dx%d, pitch: %d\nlocked: %d, refcount: %d\n",
   142            s->flags, s->w, s->h, s->pitch, s->locked, s->refcount);
   143     sdlds_print_pixfmt_info(s->format);
   144 }
   145 
   146 
   147 
   148 SDL_Renderer *
   149 NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
   150 {
   151     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   152     SDL_DisplayMode *displayMode = &display->current_mode;
   153     SDL_Renderer *renderer;
   154     NDS_RenderData *data;
   155     int i, n;
   156     int bpp = 15;
   157     Uint32 Rmask, Gmask, Bmask, Amask;
   158 /*  Uint32 Rmask = 0x7C00, Gmask = 0x03E0, Bmask = 0x001F, Amask = 0x8000;
   159     Uint32 Rmask = 0x001F, Gmask = 0x03E0, Bmask = 0x7C00, Amask = 0x8000;
   160 */
   161 
   162     /* hard coded this to BGR555 for now */
   163     if (!SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_BGR555, &bpp,
   164                                     &Rmask, &Gmask, &Bmask, &Amask)) {
   165         SDL_SetError("Unknown display format");
   166         return NULL;
   167     }
   168 
   169     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   170     if (!renderer) {
   171         SDL_OutOfMemory();
   172         return NULL;
   173     }
   174 
   175     data = (NDS_RenderData *) SDL_malloc(sizeof(*data));
   176     if (!data) {
   177         NDS_DestroyRenderer(renderer);
   178         SDL_OutOfMemory();
   179         return NULL;
   180     }
   181     SDL_zerop(data);
   182 
   183     renderer->RenderFill = NDS_RenderFill;
   184     renderer->RenderCopy = NDS_RenderCopy;
   185     renderer->RenderPresent = NDS_RenderPresent;
   186     renderer->DestroyRenderer = NDS_DestroyRenderer;
   187     renderer->info.name = NDS_RenderDriver.info.name;
   188     renderer->info.flags = 0;
   189     renderer->window = window->id;
   190     renderer->driverdata = data;
   191     Setup_SoftwareRenderer(renderer); /* TODO: well, "TODON'T" is more like it */
   192 
   193     if (flags & SDL_RENDERER_PRESENTFLIP2) {
   194         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
   195         n = 2;
   196     } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
   197         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
   198         n = 3;
   199     } else {
   200         renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
   201         n = 1;
   202     }/*
   203     for (i = 0; i < n; ++i) {
   204         data->screens[i] =
   205             SDL_CreateRGBSurface(0, 256, 192, bpp, Rmask, Gmask, Bmask,
   206                                  Amask);
   207         if (!data->screens[i]) {
   208             NDS_DestroyRenderer(renderer);
   209             return NULL;
   210         }
   211         SDL_SetSurfacePalette(data->screens[i], display->palette);
   212         sdlds_print_surface_info(data->screens[i]);
   213     }*/
   214 
   215     data->fb = (u16*)0x06020000;
   216 
   217     return renderer;
   218 }
   219 
   220 static int
   221 NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
   222                    Uint8 a, const SDL_Rect * rect)
   223 {
   224     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   225     SDL_Rect real_rect = *rect;
   226     u16 color;
   227     int i, j;
   228 
   229     color = RGB15(r>>3,g>>3,b>>3);
   230     for (i = real_rect.x; i < real_rect.x+real_rect.w; ++i) {
   231         for (j = real_rect.y; j < real_rect.y+real_rect.h; ++j) {
   232             data->fb[(j + real_rect.y) * 256 + i + real_rect.x] = 
   233                 0x8000 | color;
   234         }
   235     }
   236     return 0;
   237 }
   238 static int
   239 NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   240                    const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   241 {
   242     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   243     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   244     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   245 
   246 #if 0
   247     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   248         SDL_Surface *target = data->screens[data->current_screen];
   249         void *pixels =
   250             (Uint8 *) target->pixels + dstrect->y * target->pitch +
   251             dstrect->x * target->format->BytesPerPixel;
   252         return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
   253                                    srcrect, display->current_mode.format,
   254                                    dstrect->w, dstrect->h, pixels,
   255                                    target->pitch);
   256     } else {
   257         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   258         SDL_Surface *target = data->screens[data->current_screen];
   259         SDL_Rect real_srcrect = *srcrect;
   260         SDL_Rect real_dstrect = *dstrect;
   261         /*sdlds_print_surface_info(surface);
   262            sdlds_print_surface_info(target); */
   263         sdlds_surf2vram(surface);
   264         return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
   265     }
   266 #endif
   267     /* copy it directly to vram */
   268     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   269     sdlds_surf2vram(surface);
   270     /*
   271     int sx = srcrect->x, sy = srcrect->y, sw = srcrect->w, sh = srcrect->h;
   272     int dx = dstrect->x, dy = dstrect->y, dw = dstrect->w, dh = dstrect->h;
   273     int si, sj, di, dj;
   274     for (sj = 0, dj = 0; sj < sh && dj < dh; ++sj, ++dj) {
   275         for (si = 0, di = 0; si < sw && di < dw; ++si, ++di) {
   276             data->fb[(dj + dy) * 256 + di + dx] = 0x8000 |
   277                 ((u16 *) surface->pixels)[(sj + sy) * (surface->w) + si +
   278                                              sx];
   279         }
   280     }*/
   281     return 0;
   282 }
   283 
   284 
   285 static void
   286 NDS_RenderPresent(SDL_Renderer * renderer)
   287 {
   288     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   289     /* Send the data to the display TODO */
   290 
   291     /* Update the flipping chain, if any */
   292     if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
   293         data->current_screen = (data->current_screen + 1) % 2;
   294     } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
   295         data->current_screen = (data->current_screen + 1) % 3;
   296     }
   297 }
   298 
   299 static void
   300 NDS_DestroyRenderer(SDL_Renderer * renderer)
   301 {
   302     NDS_RenderData *data = (NDS_RenderData *) renderer->driverdata;
   303     int i;
   304 
   305     printf("NDS_DestroyRenderer(renderer)\n");
   306     printf(" renderer: %s\n", renderer->info.name);
   307     if (data) {
   308         /*for (i = 0; i < SDL_arraysize(data->screens); ++i) {
   309             if (data->screens[i]) {
   310                 SDL_FreeSurface(data->screens[i]);
   311             }
   312         }*/
   313         SDL_free(data);
   314     }
   315     SDL_free(renderer);
   316 }
   317 
   318 /* vi: set ts=4 sw=4 expandtab: */