src/video/nds/SDL_ndsrender.c
author Darren Alton <dalton@stevens.edu>
Tue, 17 Jun 2008 08:26:36 +0000
branchgsoc2008_nds
changeset 2672 74ac057679d5
parent 2671 c3e7c0698cbb
child 2673 24a6b3588eac
permissions -rw-r--r--
NDS video driver is now functional, using software rendering and framebuffer.
     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 *SDL_NDS_CreateRenderer(SDL_Window * window,
    38                                             Uint32 flags);
    39 static int SDL_NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
    40                               Uint8 b, Uint8 a, const SDL_Rect * rect);
    41 static int SDL_NDS_RenderCopy(SDL_Renderer * renderer,
    42                               SDL_Texture * texture,
    43                               const SDL_Rect * srcrect,
    44                               const SDL_Rect * dstrect);
    45 static void SDL_NDS_RenderPresent(SDL_Renderer * renderer);
    46 static void SDL_NDS_DestroyRenderer(SDL_Renderer * renderer);
    47 
    48 
    49 SDL_RenderDriver SDL_NDS_RenderDriver = {
    50     SDL_NDS_CreateRenderer,
    51     {"nds", SDL_RENDERER_PRESENTCOPY}
    52 /*   (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
    53       SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
    54       SDL_RENDERER_PRESENTDISCARD),*/
    55 };
    56 
    57 typedef struct
    58 {
    59     int current_screen;
    60     SDL_Surface *screens[3];
    61     int ultimate_answer;
    62 } SDL_NDS_RenderData;
    63 
    64 
    65 
    66 /* this is mainly hackish testing/debugging stuff to get cleaned up soon
    67    anything named sdlds_blah shouldn't make it into the stable version
    68  */
    69 
    70 u16
    71 sdlds_rgb2bgr(u16 c) {
    72 /* hack to get the colors right until I actually add BGR555 to the headers */
    73     u16 Rmask = 0x7C00, Bmask = 0x001F, GAmask = 0x83E0, r, b;
    74     r = (c & Rmask) >> 10;
    75     b = (c & Bmask) << 10;
    76     return (c & GAmask) | r | b;
    77 }
    78 
    79 void
    80 sdlds_surf2vram(SDL_Surface * s)
    81 {
    82 
    83     int i;
    84 	/*for (i = 0; i < 30; ++i) swiWaitForVBlank();*/
    85     for (i = 0; i < 256 * 192; ++i) {
    86         ((u16 *) VRAM_A)[i] = sdlds_rgb2bgr(((u16 *) (s->pixels))[i+160]);
    87     }
    88 }
    89 
    90 void
    91 sdlds_print_pixfmt_info(SDL_PixelFormat *f) {
    92 	if(!f) return;
    93 	printf("bpp: %d\nRGBA: %x %x %x %x\n",
    94 	       f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
    95 }
    96 
    97 void
    98 sdlds_print_surface_info(SDL_Surface *s) {
    99 	if(!s) return;
   100 	printf("flags: %x\nsize: %dx%d, pitch: %d\nlocked: %d, refcount: %d\n",
   101 	       s->flags, s->w, s->h, s->pitch, s->locked, s->refcount);
   102 	sdlds_print_pixfmt_info(s->format);
   103 }
   104 
   105 
   106 
   107 SDL_Renderer *
   108 SDL_NDS_CreateRenderer(SDL_Window * window, Uint32 flags)
   109 {
   110     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   111     SDL_DisplayMode *displayMode = &display->current_mode;
   112     SDL_Renderer *renderer;
   113     SDL_NDS_RenderData *data;
   114     int i, n;
   115     int bpp = 15;
   116 /*/
   117     Uint32 Rmask = 0x7C00, Gmask = 0x03E0, Bmask = 0x001F, Amask = 0x8000;
   118 /*/
   119     Uint32 Rmask = 0x001F, Gmask = 0x03E0, Bmask = 0x7C00, Amask = 0x8000;
   120 //*/
   121 
   122 #if 0
   123     printf("SDL_NDS_CreateRenderer(window, 0x%x)\n", flags);
   124     printf(" window: (%d,%d), %dx%d\n",
   125            window->x, window->y, window->w, window->h);
   126 #endif
   127 
   128     /* hard coded this to ARGB1555 for now
   129        if (!SDL_PixelFormatEnumToMasks
   130        (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
   131        SDL_SetError("Unknown display format");
   132        return NULL;
   133        } */
   134 
   135     renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
   136     if (!renderer) {
   137         SDL_OutOfMemory();
   138         return NULL;
   139     }
   140 
   141     data = (SDL_NDS_RenderData *) SDL_malloc(sizeof(*data));
   142     if (!data) {
   143         SDL_NDS_DestroyRenderer(renderer);
   144         SDL_OutOfMemory();
   145         return NULL;
   146     }
   147     SDL_zerop(data);
   148 
   149     renderer->RenderFill = SDL_NDS_RenderFill;
   150     renderer->RenderCopy = SDL_NDS_RenderCopy;
   151     renderer->RenderPresent = SDL_NDS_RenderPresent;
   152     renderer->DestroyRenderer = SDL_NDS_DestroyRenderer;
   153     renderer->info.name = SDL_NDS_RenderDriver.info.name;
   154     renderer->info.flags = 0;
   155     renderer->window = window->id;
   156     renderer->driverdata = data;
   157     Setup_SoftwareRenderer(renderer);
   158 
   159     if (flags & SDL_RENDERER_PRESENTFLIP2) {
   160         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
   161         n = 2;
   162     } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
   163         renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
   164         n = 3;
   165     } else {
   166         renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
   167         n = 1;
   168     }
   169     for (i = 0; i < n; ++i) {
   170         data->screens[i] =
   171             SDL_CreateRGBSurface(0, 256, 192, bpp, Rmask, Gmask, Bmask, Amask);
   172         if (!data->screens[i]) {
   173             SDL_NDS_DestroyRenderer(renderer);
   174             return NULL;
   175         }
   176         SDL_SetSurfacePalette(data->screens[i], display->palette);
   177     }
   178 
   179     data->current_screen = 0;
   180     data->ultimate_answer = 42;
   181 
   182     return renderer;
   183 }
   184 
   185 static int
   186 SDL_NDS_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
   187                    Uint8 a, const SDL_Rect * rect)
   188 {
   189     SDL_NDS_RenderData *data = (SDL_NDS_RenderData *) renderer->driverdata;
   190     SDL_Surface *target = data->screens[data->current_screen];
   191     Uint32 color;
   192     SDL_Rect real_rect = *rect;
   193 
   194     color = SDL_MapRGBA(target->format, r, g, b, a);
   195 
   196     return SDL_FillRect(target, &real_rect, color);
   197 }
   198 
   199 static int
   200 SDL_NDS_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   201                    const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   202 {
   203     SDL_NDS_RenderData *data = (SDL_NDS_RenderData *) renderer->driverdata;
   204     SDL_Window *window = SDL_GetWindowFromID(renderer->window);
   205     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
   206 #if 0
   207     printf("SDL_NDS_RenderCopy(renderer, texture, srcrect, dstrect)\n");
   208     printf(" renderer: %s\n", renderer->info.name);
   209     printf(" texture: %dx%d\n", texture->w, texture->h);
   210     printf(" srcrect: (%d,%d), %dx%d\n", srcrect->x, srcrect->y, srcrect->w,
   211            srcrect->h);
   212     printf(" dstrect: (%d,%d), %dx%d\n", dstrect->x, dstrect->y, dstrect->w,
   213            dstrect->h);
   214 #endif
   215     if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
   216         SDL_Surface *target = data->screens[data->current_screen];
   217         void *pixels =
   218             (Uint8 *) target->pixels + dstrect->y * target->pitch +
   219             dstrect->x * target->format->BytesPerPixel;
   220         return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
   221                                    srcrect, display->current_mode.format,
   222                                    dstrect->w, dstrect->h, pixels,
   223                                    target->pitch);
   224     } else {
   225         SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   226         SDL_Surface *target = data->screens[data->current_screen];
   227         SDL_Rect real_srcrect = *srcrect;
   228         SDL_Rect real_dstrect = *dstrect;
   229         /*sdlds_print_surface_info(surface);
   230         sdlds_print_surface_info(target);*/
   231         sdlds_surf2vram(surface);
   232         return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
   233     }
   234 #if 0
   235     /* copy it directly to vram */
   236     SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
   237     int sx = srcrect->x, sy = srcrect->y, sw = srcrect->w, sh = srcrect->h;
   238     int dx = dstrect->x, dy = dstrect->y, dw = dstrect->w, dh = dstrect->h;
   239     int si, sj, di, dj;
   240     for (sj = 0, dj = 0; sj < sh && dj < dh; ++sj, ++dj) {
   241         for (si = 0, di = 0; si < sw && di < dw; ++si, ++di) {
   242             VRAM_A[(dj + dy) * 256 + di + dx] =
   243               ((Uint16 *) surface->pixels)[(sj + sy) * (surface->w) + si + sx];
   244         }
   245     }
   246     return 0;
   247 #endif
   248 }
   249 
   250 
   251 static void
   252 SDL_NDS_RenderPresent(SDL_Renderer * renderer)
   253 {
   254     SDL_NDS_RenderData *data = (SDL_NDS_RenderData *) renderer->driverdata;
   255 #if 0
   256     printf("SDL_NDS_RenderPresent(renderer)\n");
   257     printf(" renderer: %s\n", renderer->info.name);
   258 #endif
   259     /* Send the data to the display */
   260     /*sdlds_surf2vram(data->screens[data->current_screen]);*/
   261 
   262     /* Update the flipping chain, if any */
   263     if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
   264         data->current_screen = (data->current_screen + 1) % 2;
   265     } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
   266         data->current_screen = (data->current_screen + 1) % 3;
   267     }
   268 }
   269 
   270 static void
   271 SDL_NDS_DestroyRenderer(SDL_Renderer * renderer)
   272 {
   273     SDL_NDS_RenderData *data = (SDL_NDS_RenderData *) renderer->driverdata;
   274     int i;
   275 
   276     printf("SDL_NDS_DestroyRenderer(renderer)\n");
   277     printf(" renderer: %s\n", renderer->info.name);
   278     if (data) {
   279         for (i = 0; i < SDL_arraysize(data->screens); ++i) {
   280             if (data->screens[i]) {
   281                 SDL_FreeSurface(data->screens[i]);
   282             }
   283         }
   284         SDL_free(data);
   285     }
   286     SDL_free(renderer);
   287 }
   288 
   289 /* vi: set ts=4 sw=4 expandtab: */