static mrb_value mrb_sdl_video_unlock_surface (mrb_state *mrb, mrb_value self) { mrb_value surface = mrb_nil_value(); mrb_get_args(mrb, "|o", &surface); SDL_UnlockSurface(mrb_value_to_sdl_surface(mrb, surface)); return mrb_nil_value(); }
/* Overridable function, if necessary, for doing all of the drawing. Base class version checks whether a redraw is needed and does nothing if not. See Redraw() function. If a redraw is needed then there is an option to either redraw the whole screen or just redraw the moving objects. If redrawing the whole screen then: 1a) SetupBackgroundBuffer is called to draw the background to the background buffer. 1b) DrawScreen is called to copy the background buffer onto the screen, then draw the moving objects. 1c) SDL_UpdateRect() is called to actually redraw the whole screen. If only redrawing the moving objects then: 2a) DrawChangingObjects() is called to remove the objects from their old positions, and redraw them in their new positions. 2b) GetUpdateRectanglesForChangingObjects() is called to calculate where on the screen needs redrawing. 2c) SDL_UpdateRects() is called to redraw the parts of the screen which changed. */ void BaseEngine::GameRender(void) { if ( !m_bNeedsRedraw ) return; // Just drawn so no more redraw needed m_bNeedsRedraw = false; // Note: the redraw flags must only be set early in this method, not at the end, since the drawing/moving of the moving objects may // potentially flag a win/lose condition and a state change, which will set the redraw flag again to force a full draw after the // state changes. if ( m_bWholeScreenUpdate ) { // Drawn whole screen now, so no need to draw it again. See note above about the importance of not resetting this after DrawChangingObjects() m_bWholeScreenUpdate = false; // Lock surface if needed if (SDL_MUSTLOCK(m_pActualScreen)) { m_bInsideDraw = true; if (SDL_LockSurface(m_pActualScreen) < 0) return; } // Draw the screen as it should appear now. // First draw the background //this->CopyBackgroundPixels( 100, 100, 100, 100 ); CopyAllBackgroundBuffer(); // Draw the text for the user DrawStrings(); // Single function in case people want to use that instead DrawStringsUnderneath(); // Draw the string underneath the other objects here // Then draw the changing objects DrawObjects(); // Another option for where to put the draw strings code - if you want it on top of the moving objects DrawStringsOnTop(); // Unlock if needed if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); m_bInsideDraw = false; SDL_UpdateTexture( m_pSDL2Texture,NULL,m_pActualScreen->pixels,m_pActualScreen->pitch ); //SDL_RenderClear( m_pSDL2Renderer ); SDL_RenderCopy( m_pSDL2Renderer,m_pSDL2Texture,NULL,NULL ); SDL_RenderPresent( m_pSDL2Renderer ); //SDL_UpdateRect(m_pActualScreen, 0, 0, m_iScreenWidth, m_iScreenHeight); } else { // Here we assume that the background buffer has already been set up // Lock surface if needed if (SDL_MUSTLOCK(m_pActualScreen)) { m_bInsideDraw = true; if (SDL_LockSurface(m_pActualScreen) < 0) return; } // Remove objects from their old positions UndrawObjects(); // Remove the old strings be re-drawing the background UnDrawStrings(); // Draw the text for the user DrawStrings(); // Single function in case people want to use that instead DrawStringsUnderneath(); // Draw the string underneath the other objects here // Draw objects at their new positions DrawObjects(); // Another option for where to put the draw strings code - if you want it on top of the moving objects DrawStringsOnTop(); // Unlock if needed if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); m_bInsideDraw = false; // Copy the screen display into the window and display it SDL_UpdateTexture( m_pSDL2Texture,NULL,m_pActualScreen->pixels,m_pActualScreen->pitch ); //SDL_RenderClear( m_pSDL2Renderer ); SDL_RenderCopy( m_pSDL2Renderer,m_pSDL2Texture,NULL,NULL ); SDL_RenderPresent( m_pSDL2Renderer ); } }
/* The general purpose software blit routine */ static int SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { int okay; int src_locked; int dst_locked; /* Everything is okay at the beginning... */ okay = 1; /* Lock the destination if it's in hardware */ dst_locked = 0; if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { okay = 0; } else { dst_locked = 1; } } /* Lock the source if it's in hardware */ src_locked = 0; if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { okay = 0; } else { src_locked = 1; } } /* Set up source and destination buffer pointers, and BLIT! */ if (okay && !SDL_RectEmpty(srcrect)) { SDL_BlitFunc RunBlit; SDL_BlitInfo *info = &src->map->info; /* Set up the blit information */ info->src = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * info->src_fmt->BytesPerPixel; info->src_w = srcrect->w; info->src_h = srcrect->h; info->src_pitch = src->pitch; info->src_skip = info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel; info->dst = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * info->dst_fmt->BytesPerPixel; info->dst_w = dstrect->w; info->dst_h = dstrect->h; info->dst_pitch = dst->pitch; info->dst_skip = info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel; RunBlit = (SDL_BlitFunc) src->map->data; /* Run the actual software blit */ RunBlit(info); } /* We need to unlock the surfaces if they're locked */ if (dst_locked) { SDL_UnlockSurface(dst); } if (src_locked) { SDL_UnlockSurface(src); } /* Blit is done! */ return (okay ? 0 : -1); }
/** * @brief Loads a surface into an opengl texture. * * @param surface Surface to load into a texture. * @param flags Flags to use. * @param[out] rw Real width of the texture. * @param[out] rh Real height of the texture. * @return The opengl texture id. */ static GLuint gl_loadSurface( SDL_Surface* surface, int *rw, int *rh, unsigned int flags, int freesur ) { GLuint texture; GLfloat param; /* Prepare the surface. */ surface = gl_prepareSurface( surface ); if (rw != NULL) (*rw) = surface->w; if (rh != NULL) (*rh) = surface->h; /* opengl texture binding */ glGenTextures( 1, &texture ); /* Creates the texture */ glBindTexture( GL_TEXTURE_2D, texture ); /* Loads the texture */ /* Filtering, LINEAR is better for scaling, nearest looks nicer, LINEAR * also seems to create a bit of artifacts around the edges */ if ((gl_screen.scale != 1.) || (flags & OPENGL_TEX_MIPMAPS)) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } /* Always wrap just in case. */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); /* now lead the texture data up */ SDL_LockSurface( surface ); if (gl_texHasCompress()) { glTexImage2D( GL_TEXTURE_2D, 0, surface->format->BytesPerPixel, surface->w, surface->h, 0, GL_COMPRESSED_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); } else { glTexImage2D( GL_TEXTURE_2D, 0, surface->format->BytesPerPixel, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); } SDL_UnlockSurface( surface ); /* Create mipmaps. */ if ((flags & OPENGL_TEX_MIPMAPS) && gl_texHasMipmaps()) { /* Do fancy stuff. */ if (gl_hasExt("GL_EXT_texture_filter_anisotropic")) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, ¶m); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, param); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 9); /* Now generate the mipmaps. */ nglGenerateMipmap(GL_TEXTURE_2D); } /* cleanup */ if (freesur) SDL_FreeSurface( surface ); gl_checkErr(); return texture; }
int SDL_SaveBMP_RW (SDL_Surface *saveme, SDL_RWops *dst, int freedst) { long fp_offset; int i, pad; SDL_Surface *surface; Uint8 *bits; /* The Win32 BMP file header (14 bytes) */ char magic[2] = { 'B', 'M' }; Uint32 bfSize; Uint16 bfReserved1; Uint16 bfReserved2; Uint32 bfOffBits; /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ Uint32 biSize; Sint32 biWidth; Sint32 biHeight; Uint16 biPlanes; Uint16 biBitCount; Uint32 biCompression; Uint32 biSizeImage; Sint32 biXPelsPerMeter; Sint32 biYPelsPerMeter; Uint32 biClrUsed; Uint32 biClrImportant; /* Make sure we have somewhere to save */ surface = NULL; if ( dst ) { if ( saveme->format->palette ) { if ( saveme->format->BitsPerPixel == 8 ) { surface = saveme; } else { SDL_SetError("%d bpp BMP files not supported", saveme->format->BitsPerPixel); } } else if ( (saveme->format->BitsPerPixel == 24) && #if SDL_BYTEORDER == SDL_LIL_ENDIAN (saveme->format->Rmask == 0x00FF0000) && (saveme->format->Gmask == 0x0000FF00) && (saveme->format->Bmask == 0x000000FF) #else (saveme->format->Rmask == 0x000000FF) && (saveme->format->Gmask == 0x0000FF00) && (saveme->format->Bmask == 0x00FF0000) #endif ) { surface = saveme; } else { SDL_Rect bounds; /* Convert to 24 bits per pixel */ surface = SDL_CreateRGBSurface(SDL_SWSURFACE, saveme->w, saveme->h, 24, #if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x00FF0000, 0x0000FF00, 0x000000FF, #else 0x000000FF, 0x0000FF00, 0x00FF0000, #endif 0); if ( surface != NULL ) { bounds.x = 0; bounds.y = 0; bounds.w = saveme->w; bounds.h = saveme->h; if ( SDL_LowerBlit(saveme, &bounds, surface, &bounds) < 0 ) { SDL_FreeSurface(surface); SDL_SetError( "Couldn't convert image to 24 bpp"); surface = NULL; } } } } if ( surface && (SDL_LockSurface(surface) == 0) ) { const int bw = surface->w*surface->format->BytesPerPixel; /* Set the BMP file header values */ bfSize = 0; /* We'll write this when we're done */ bfReserved1 = 0; bfReserved2 = 0; bfOffBits = 0; /* We'll write this when we're done */ /* Write the BMP file header values */ fp_offset = SDL_RWtell(dst); SDL_ClearError(); SDL_RWwrite(dst, magic, 2, 1); SDL_WriteLE32(dst, bfSize); SDL_WriteLE16(dst, bfReserved1); SDL_WriteLE16(dst, bfReserved2); SDL_WriteLE32(dst, bfOffBits); /* Set the BMP info values */ biSize = 40; biWidth = surface->w; biHeight = surface->h; biPlanes = 1; biBitCount = surface->format->BitsPerPixel; biCompression = BI_RGB; biSizeImage = surface->h*surface->pitch; biXPelsPerMeter = 0; biYPelsPerMeter = 0; if ( surface->format->palette ) { biClrUsed = surface->format->palette->ncolors; } else { biClrUsed = 0; } biClrImportant = 0; /* Write the BMP info values */ SDL_WriteLE32(dst, biSize); SDL_WriteLE32(dst, biWidth); SDL_WriteLE32(dst, biHeight); SDL_WriteLE16(dst, biPlanes); SDL_WriteLE16(dst, biBitCount); SDL_WriteLE32(dst, biCompression); SDL_WriteLE32(dst, biSizeImage); SDL_WriteLE32(dst, biXPelsPerMeter); SDL_WriteLE32(dst, biYPelsPerMeter); SDL_WriteLE32(dst, biClrUsed); SDL_WriteLE32(dst, biClrImportant); /* Write the palette (in BGR color order) */ if ( surface->format->palette ) { SDL_Color *colors; int ncolors; colors = surface->format->palette->colors; ncolors = surface->format->palette->ncolors; for ( i=0; i<ncolors; ++i ) { SDL_RWwrite(dst, &colors[i].b, 1, 1); SDL_RWwrite(dst, &colors[i].g, 1, 1); SDL_RWwrite(dst, &colors[i].r, 1, 1); SDL_RWwrite(dst, &colors[i].unused, 1, 1); } } /* Write the bitmap offset */ bfOffBits = SDL_RWtell(dst)-fp_offset; if ( SDL_RWseek(dst, fp_offset+10, RW_SEEK_SET) < 0 ) { SDL_Error(SDL_EFSEEK); } SDL_WriteLE32(dst, bfOffBits); if ( SDL_RWseek(dst, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) { SDL_Error(SDL_EFSEEK); } /* Write the bitmap image upside down */ bits = (Uint8 *)surface->pixels+(surface->h*surface->pitch); pad = ((bw%4) ? (4-(bw%4)) : 0); while ( bits > (Uint8 *)surface->pixels ) { bits -= surface->pitch; if ( SDL_RWwrite(dst, bits, 1, bw) != bw) { SDL_Error(SDL_EFWRITE); break; } if ( pad ) { const Uint8 padbyte = 0; for ( i=0; i<pad; ++i ) { SDL_RWwrite(dst, &padbyte, 1, 1); } } } /* Write the BMP file size */ bfSize = SDL_RWtell(dst)-fp_offset; if ( SDL_RWseek(dst, fp_offset+2, RW_SEEK_SET) < 0 ) { SDL_Error(SDL_EFSEEK); } SDL_WriteLE32(dst, bfSize); if ( SDL_RWseek(dst, fp_offset+bfSize, RW_SEEK_SET) < 0 ) { SDL_Error(SDL_EFSEEK); } /* Close it up.. */ SDL_UnlockSurface(surface); if ( surface != saveme ) { SDL_FreeSurface(surface); } } if ( freedst && dst ) { SDL_RWclose(dst); } return((SDL_strcmp(SDL_GetError(), "") == 0) ? 0 : -1); }
static void isoactor_load_cfields(struct isoactor *actor, int ctw, int cth, const char *c_sprite_filename) { SDL_Surface *image; int images_wide, images_high; int hindex, windex, index; int ba_h = ceil(actor->ch / cth); /* Height of the bitmask array */ int ba_w = ceil(actor->cw / ctw); /* Width of the bitmask array */ int (*ba)[ba_w]; /* Bitmask array */ Uint32 maskcolour; if(ba_w > ISO_BFBW) { fprintf(stderr, "Error! Collision tilemap is too wide " "for bitmask variable. \n"); return; } /* Load the image file that contains the collision sprites */ image = IMG_Load(c_sprite_filename); if(!image) { fprintf(stderr, "Error! Could not load collision sprite: %s\n", c_sprite_filename); return; } maskcolour = SDL_MapRGB(image->format, 0, 0, 0); /* Calculate how many sprite images are contained on the * surface we have been given */ images_wide = (int)(image->w/actor->cw); images_high = (int)(image->h/actor->ch); ba = malloc(ba_h * ba_w * sizeof(*ba)); if(!ba) { fprintf(stderr, "Error! Could not malloc bitmask array\n"); SDL_FreeSurface(image); return; } for(hindex = 0; hindex < images_high; hindex++) { for(windex = 0; windex < images_wide; windex++) { index = hindex * images_wide + windex; memset(ba, 0, sizeof(ba) * ba_h * ba_w); #ifdef DEBUG_MODE fprintf(stderr, "loading collision sprite index %d\n\n", index); #endif SDL_LockSurface(image); int i, j; for(i = 0; i < actor->ch; i++) { for(j = 0; j < actor->cw; j++) { if(get_pixel(image, j + windex * actor->cw, (actor->ch - 1 - i) + hindex * actor->ch) == maskcolour) { ba[i / cth][j / ctw] += 1; } } } SDL_UnlockSurface(image); actor->cfields[index] = malloc(ba_h * sizeof(*(actor->cfields[index]))); if(!(actor->cfields[index])) { fprintf(stderr, "Error! Could not allocate memory for collision bit-field\n"); return; } memset(actor->cfields[index], 0, ba_h * sizeof(isobf_t)); for(i = 0; i < ba_h; i++) { for(j = 0; j < ba_w; j++) { if(ba[i][j] > ctw * cth / 2.) { /* This line produces the binary number * 00010000000 where there are j 0's before * the leading 1 */ actor->cfields[index][i] |= (isobf_t)1 << (ISO_BFBW - j - 1); #ifdef DEBUG_MODE fprintf(stderr, "1"); #endif } else { #ifdef DEBUG_MODE fprintf(stderr, "0"); #endif } } #ifdef DEBUG_MODE fprintf(stderr, "\n"); #endif } } } #ifdef DEBUG_MODE fprintf(stderr, "\n"); #endif free(ba); return; }
void Render(void) { static int sn = 0; if (params.antiFlicker) { renderSurf = scrSurf[sn]; sn = 1 - sn; } else renderSurf = screen; if ((drawFrame || isAvgImageWrited /* isLongImageWrited */) && SDL_MUSTLOCK(renderSurf)) { if (SDL_LockSurface(renderSurf) < 0) { printf("Can't lock surface\n"); return; } } renderPitch = renderSurf->pitch / 4; if (dev_extport.Is16Colors()) renderPtr = Render16c; else if (dev_extport.IsMulticolor()) renderPtr = RenderMulticolor; // else if (dev_extport.Is512x192()) renderPtr = Render512x192; // else if (dev_extport.Is384x304()) renderPtr = Render384x304; else renderPtr = RenderSpeccy; InitActClk(); prevRenderClk = 0; while (cpuClk < INT_LENGTH) { CpuStep(); CpuInt(); } if (drawFrame || isAvgImageWrited /* isLongImageWrited */) { while (cpuClk < MAX_FRAME_TACTS) { CpuStep(); renderPtr(cpuClk); } } else { while (cpuClk < MAX_FRAME_TACTS) { CpuStep(); } } renderPtr = NULL; lastDevClk = devClk; cpuClk -= MAX_FRAME_TACTS; devClk = cpuClk; if ((drawFrame || isAvgImageWrited /* isLongImageWrited */) && SDL_MUSTLOCK(renderSurf)) SDL_UnlockSurface(renderSurf); if (params.antiFlicker && (drawFrame || isAvgImageWrited /* isLongImageWrited */)) AntiFlicker(renderSurf, scrSurf[sn]); // if (isLongImageWrited) // { // int * src = (int *)screen->pixels + (PITCH * (32 + longImagePos)) + 32; // // for (int i = 256; i--;) // { // unsigned int c = *src; // int r = GETR(c); // int g = GETG(c); // int b = GETB(c); // // longImageFile.PutBYTE(r); // longImageFile.PutBYTE(g); // longImageFile.PutBYTE(b); // // *(src++) = DRGB(255 - r, 255 - g, 255 - b); // } // // longImageHeight++; // longImagePos = (longImagePos + 1) % 192; // } if (isAvgImageWrited) { int * src = (int *)screen->pixels; long * dst = avgImageBuffer; for (int i = HEIGHT; i--;) { int * line = src; for (int j = WIDTH; j--;) { unsigned int c = *(line++); *(dst++) += (long)GETR(c); *(dst++) += (long)GETG(c); *(dst++) += (long)GETB(c); } src += PITCH; } // avgImageFrames++; } }
/** * @brief Wrapper for gl_loadImagePad that includes transparency mapping. * * @param name Name to load with. * @param surface Surface to load. * @param rw RWops containing data to hash. * @param flags Flags to use. * @param w Non-padded width. * @param h Non-padded height. * @param sx X sprites. * @param sy Y sprites. * @param freesur Whether or not to free the surface. * @return The glTexture for surface. */ glTexture* gl_loadImagePadTrans( const char *name, SDL_Surface* surface, SDL_RWops *rw, unsigned int flags, int w, int h, int sx, int sy, int freesur ) { glTexture *texture; int i, filesize; size_t cachesize, pngsize; uint8_t *trans; char *cachefile, *data; char digest[33]; md5_state_t md5; md5_byte_t *md5val; if (name != NULL) { texture = gl_texExists( name ); if (texture != NULL) return texture; } if (flags & OPENGL_TEX_MAPTRANS) flags ^= OPENGL_TEX_MAPTRANS; /* Appropriate size for the transparency map, see SDL_MapTrans */ cachesize = gl_transSize(w, h); cachefile = NULL; trans = NULL; if (rw != NULL) { md5val = malloc(16); md5_init(&md5); pngsize = SDL_RWseek( rw, 0, SEEK_END ); SDL_RWseek( rw, 0, SEEK_SET ); data = malloc(pngsize); if (data == NULL) WARN("Out of memory!"); else { SDL_RWread( rw, data, pngsize, 1 ); md5_append( &md5, (md5_byte_t*)data, pngsize ); free(data); } md5_finish( &md5, md5val ); for (i=0; i<16; i++) nsnprintf( &digest[i * 2], 3, "%02x", md5val[i] ); free(md5val); cachefile = malloc( PATH_MAX ); nsnprintf( cachefile, PATH_MAX, "%scollisions/%s", nfile_cachePath(), digest ); /* Attempt to find a cached transparency map. */ if (nfile_fileExists(cachefile)) { trans = (uint8_t*)nfile_readFile( &filesize, cachefile ); /* Consider cached data invalid if the length doesn't match. */ if (trans != NULL && cachesize != (unsigned int)filesize) { free(trans); trans = NULL; } /* Cached data matches, no need to overwrite. */ else { free(cachefile); cachefile = NULL; } } } else { /* We could hash raw pixel data here, but that's slower than just * generating the map from scratch. */ WARN("Texture '%s' has no RWops", name); } if (trans == NULL) { SDL_LockSurface(surface); trans = SDL_MapTrans( surface, w, h ); SDL_UnlockSurface(surface); if (cachefile != NULL) { /* Cache newly-generated transparency map. */ nfile_dirMakeExist( "%s/collisions/", nfile_cachePath() ); nfile_writeFile( (char*)trans, cachesize, cachefile ); free(cachefile); } } texture = gl_loadImagePad( name, surface, flags, w, h, sx, sy, freesur ); texture->trans = trans; return texture; }
SDLImageLoader::~SDLImageLoader() { SDL_UnlockSurface(image->surf); SDL_SetColorKey(image->surf, SDL_TRUE, 0); //TODO: RLE if compressed and bpp>1 }
/* * out_unlock_surface - unlock output surface */ void out_unlock_surface () { SDL_UnlockSurface (out_surface); }
void DrawPict(SDL_Surface *screen, char *bmpfile, int speedy, int flip, int nofade) { SDL_Surface *picture; SDL_Rect dest, update; int i, centered; int ncolors; SDL_Color *colors, *cmap; /* Load the image into a surface */ if ( bmpfile == NULL ) { bmpfile = "sample.bmp"; /* Sample image */ } fprintf(stderr, "Loading picture: %s\n", bmpfile); picture = SDL_LoadBMP(bmpfile); if ( picture == NULL ) { fprintf(stderr, "Couldn't load %s: %s\n", bmpfile, SDL_GetError()); return; } /* Set the display colors -- on a hicolor display this is a no-op */ if ( picture->format->palette ) { ncolors = picture->format->palette->ncolors; colors = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color)); cmap = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color)); memcpy(colors, picture->format->palette->colors, ncolors*sizeof(SDL_Color)); } else { int r, g, b; /* Allocate 256 color palette */ ncolors = 256; colors = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color)); cmap = (SDL_Color *)malloc(ncolors*sizeof(SDL_Color)); /* Set a 3,3,2 color cube */ for ( r=0; r<8; ++r ) { for ( g=0; g<8; ++g ) { for ( b=0; b<4; ++b ) { i = ((r<<5)|(g<<2)|b); colors[i].r = r<<5; colors[i].g = g<<5; colors[i].b = b<<6; } } } } NOTICE("testwin: setting colors\n"); if ( ! SDL_SetColors(screen, colors, 0, ncolors) && (screen->format->palette != NULL) ) { fprintf(stderr, "Warning: Couldn't set all of the colors, but SDL will map the image\n" " (colormap fading will suffer - try the -warp option)\n" ); } /* Set the screen to black (not really necessary) */ if ( SDL_LockSurface(screen) == 0 ) { Uint32 black; Uint8 *pixels; black = SDL_MapRGB(screen->format, 0, 0, 0); pixels = (Uint8 *)screen->pixels; for ( i=0; i<screen->h; ++i ) { memset(pixels, black, screen->w*screen->format->BytesPerPixel); pixels += screen->pitch; } SDL_UnlockSurface(screen); SDL_UpdateRect(screen, 0, 0, 0, 0); } /* Display the picture */ if ( speedy ) { SDL_Surface *displayfmt; fprintf(stderr, "Converting picture\n"); displayfmt = SDL_DisplayFormat(picture); if ( displayfmt == NULL ) { fprintf(stderr, "Couldn't convert image: %s\n", SDL_GetError()); goto done; } SDL_FreeSurface(picture); picture = displayfmt; } printf("(image surface located in %s memory)\n", (picture->flags&SDL_HWSURFACE) ? "video" : "system"); centered = (screen->w - picture->w)/2; if ( centered < 0 ) { centered = 0; } dest.y = (screen->h - picture->h)/2; dest.w = picture->w; dest.h = picture->h; NOTICE("testwin: moving image\n"); for ( i=0; i<=centered; ++i ) { dest.x = i; update = dest; if ( SDL_BlitSurface(picture, NULL, screen, &update) < 0 ) { fprintf(stderr, "Blit failed: %s\n", SDL_GetError()); break; } if ( flip ) { SDL_Flip(screen); } else { SDL_UpdateRects(screen, 1, &update); } } #ifdef SCREENSHOT if ( SDL_SaveBMP(screen, "screen.bmp") < 0 ) printf("Couldn't save screen: %s\n", SDL_GetError()); #endif #ifndef BENCHMARK_SDL /* Let it sit there for a while */ SDL_Delay(5*1000); #endif /* Fade the colormap */ if ( ! nofade ) { int maxstep; SDL_Color final; SDL_Color palcolors[256]; struct { Sint16 r, g, b; } cdist[256]; NOTICE("testwin: fading out...\n"); memcpy(cmap, colors, ncolors*sizeof(SDL_Color)); maxstep = 32-1; final.r = 0xFF;
/** ** Toggle full screen mode. */ void ToggleFullScreen() { #ifdef USE_MAEMO // On Maemo is only supported fullscreen mode return; #endif #ifdef USE_WIN32 long framesize; SDL_Rect clip; Uint32 flags; int w; int h; int bpp; unsigned char *pixels = NULL; SDL_Color *palette = NULL; int ncolors = 0; if (!TheScreen) { // don't bother if there's no surface. return; } flags = TheScreen->flags; w = TheScreen->w; h = TheScreen->h; bpp = TheScreen->format->BitsPerPixel; if (!SDL_VideoModeOK(w, h, bpp, flags ^ SDL_FULLSCREEN)) { return; } SDL_GetClipRect(TheScreen, &clip); // save the contents of the screen. framesize = w * h * TheScreen->format->BytesPerPixel; #if defined(USE_OPENGL) || defined(USE_GLES) if (!UseOpenGL) #endif { if (!(pixels = new unsigned char[framesize])) { // out of memory return; } SDL_LockSurface(TheScreen); memcpy(pixels, TheScreen->pixels, framesize); if (TheScreen->format->palette) { ncolors = TheScreen->format->palette->ncolors; if (!(palette = new SDL_Color[ncolors])) { delete[] pixels; return; } memcpy(palette, TheScreen->format->palette->colors, ncolors * sizeof(SDL_Color)); } SDL_UnlockSurface(TheScreen); } TheScreen = SDL_SetVideoMode(w, h, bpp, flags ^ SDL_FULLSCREEN); if (!TheScreen) { TheScreen = SDL_SetVideoMode(w, h, bpp, flags); if (!TheScreen) { // completely screwed. #if defined(USE_OPENGL) || defined(USE_GLES) if (!UseOpenGL) #endif { delete[] pixels; delete[] palette; } fprintf(stderr, "Toggle to fullscreen, crashed all\n"); Exit(-1); } } #ifndef USE_TOUCHSCREEN // Cannot hide cursor on Windows with touchscreen, as it switches // to relative mouse coordinates in fullscreen. See above initial // call to ShowCursor // // Windows shows the SDL cursor when starting in fullscreen mode // then switching to window mode. This hides the cursor again. SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_DISABLE); #endif #if defined(USE_OPENGL) || defined(USE_GLES) if (UseOpenGL) { ReloadOpenGL(); } else #endif { SDL_LockSurface(TheScreen); memcpy(TheScreen->pixels, pixels, framesize); delete[] pixels; if (TheScreen->format->palette) { // !!! FIXME : No idea if that flags param is right. SDL_SetPalette(TheScreen, SDL_LOGPAL, palette, 0, ncolors); delete[] palette; } SDL_UnlockSurface(TheScreen); } SDL_SetClipRect(TheScreen, &clip); Invalidate(); // Update display #else // !USE_WIN32 SDL_WM_ToggleFullScreen(TheScreen); #endif Video.FullScreen = (TheScreen->flags & SDL_FULLSCREEN) ? 1 : 0; }
bool ImageWriter::writePNG(SDL_Surface *surface, const std::string &filename) { // TODO Maybe someone can make this look nice? FILE *fp = fopen(filename.c_str(), "wb"); if (!fp) { logger->log("could not open file %s for writing", filename.c_str()); return false; } png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; int colortype; if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { logger->log("Had trouble creating png_structp"); return false; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); logger->log("Could not create png_info"); return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); logger->log("problem writing to %s", filename.c_str()); return false; } png_init_io(png_ptr, fp); colortype = (surface->format->BitsPerPixel == 24) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, 8, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); row_pointers = new png_bytep[surface->h]; if (!row_pointers) { logger->log("Had trouble converting surface to row pointers"); return false; } for (int i = 0; i < surface->h; i++) { row_pointers[i] = (png_bytep)(Uint8 *)surface->pixels + i * surface->pitch; } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); fclose(fp); delete [] row_pointers; png_destroy_write_struct(&png_ptr, (png_infopp)NULL); if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); return true; }
static void trackball_refresh( TrackBall ball ) { int diameter = ball->diameter; unsigned* pixels = ball->pixels; Fix16VectorRec faxes[3]; Fix16 dot_threshold = DOT_THRESHOLD * diameter; int nn; SDL_LockSurface( ball->surface ); fixedvector_from_vector( (Fix16Vector)&faxes[0], (Vector)&ball->axes[0] ); fixedvector_from_vector( (Fix16Vector)&faxes[1], (Vector)&ball->axes[1] ); fixedvector_from_vector( (Fix16Vector)&faxes[2], (Vector)&ball->axes[2] ); for (nn = 0; nn < ball->sphere_count; nn++) { SphereCoord coord = &ball->sphere_map[nn]; unsigned color = BACK_COLOR; if (coord->alpha > 0) { /* are we near one of the points ? */ Fix16 ax = fixedvector_dot( (Fix16Vector)&coord->f, (Fix16Vector)&faxes[0] ); Fix16 ay = fixedvector_dot( (Fix16Vector)&coord->f, (Fix16Vector)&faxes[1] ); Fix16 az = fixedvector_dot( (Fix16Vector)&coord->f, (Fix16Vector)&faxes[2] ); Fix16 best_dist = FIX16_ONE; int pp; color = ball->ball_color; for (pp = 0; pp < DOT_MAX; pp++) { Fix16VectorRec d; Fix16 dist; d[0] = ball->dots[pp][0] - ax; d[1] = ball->dots[pp][1] - ay; d[2] = ball->dots[pp][2] - az; if (d[0] > dot_threshold || d[0] < -dot_threshold || d[1] > dot_threshold || d[1] < -dot_threshold || d[2] > dot_threshold || d[2] < -dot_threshold ) continue; dist = fixedvector_len( (Fix16Vector)&d ); if (dist < best_dist) best_dist = dist; } if (best_dist < DOT_THRESHOLD) { int a = 256*(DOT_THRESHOLD - best_dist) / DOT_THRESHOLD; color = color_blend( color, ball->dot_color, a ); } if (coord->alpha < 256) { int a = coord->alpha; color = color_blend( ball->ring_color, color, a ); } else if (coord->alpha > 256) { int a = (coord->alpha - 256); color = color_blend( color, LIGHT_COLOR, a ); } } else /* coord->alpha <= 0 */ { color = ball->ring_color; if (coord->alpha < 0) { int a = -coord->alpha; color = color_blend( color, BACK_COLOR, a ); } } pixels[coord->x + diameter*coord->y] = color; } SDL_UnlockSurface( ball->surface ); }
GLTexture::GLTexture(SDL_Surface* image) : handle(), texture_width(), texture_height(), image_width(), image_height() { #ifdef GL_VERSION_ES_CM_1_0 texture_width = next_power_of_two(image->w); texture_height = next_power_of_two(image->h); #else if (GLEW_ARB_texture_non_power_of_two) { texture_width = image->w; texture_height = image->h; } else { texture_width = next_power_of_two(image->w); texture_height = next_power_of_two(image->h); } #endif image_width = image->w; image_height = image->h; #if SDL_BYTEORDER == SDL_BIG_ENDIAN SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE, texture_width, texture_height, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); #else SDL_Surface* convert = SDL_CreateRGBSurface(SDL_SWSURFACE, texture_width, texture_height, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); #endif if(convert == 0) { throw std::runtime_error("Couldn't create texture: out of memory"); } SDL_SetAlpha(image, 0, 0); SDL_BlitSurface(image, 0, convert, 0); assert_gl("before creating texture"); glGenTextures(1, &handle); try { GLenum sdl_format; if(convert->format->BytesPerPixel == 3) sdl_format = GL_RGB; else if(convert->format->BytesPerPixel == 4) sdl_format = GL_RGBA; else { sdl_format = GL_RGBA; assert(false); } glBindTexture(GL_TEXTURE_2D, handle); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef GL_UNPACK_ROW_LENGTH glPixelStorei(GL_UNPACK_ROW_LENGTH, convert->pitch/convert->format->BytesPerPixel); #else /* OpenGL ES doesn't support UNPACK_ROW_LENGTH, let's hope SDL didn't add * padding bytes, otherwise we need some extra code here... */ assert(convert->pitch == texture_width * convert->format->BytesPerPixel); #endif if(SDL_MUSTLOCK(convert)) { SDL_LockSurface(convert); } if (true) { // no not use mipmaps glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width, texture_height, 0, sdl_format, GL_UNSIGNED_BYTE, convert->pixels); } else { // build mipmaps gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, texture_width, texture_height, sdl_format, GL_UNSIGNED_BYTE, convert->pixels); } if(SDL_MUSTLOCK(convert)) { SDL_UnlockSurface(convert); } assert_gl("creating texture"); set_texture_params(); } catch(...) { glDeleteTextures(1, &handle); SDL_FreeSurface(convert); throw; } SDL_FreeSurface(convert); }
/* Compare surfaces */ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error) { int ret; int i,j; int bpp, bpp_reference; Uint8 *p, *p_reference; int dist; Uint8 R, G, B, A; Uint8 Rd, Gd, Bd, Ad; char imageFilename[128]; char referenceFilename[128]; /* Validate input surfaces */ if (surface == NULL || referenceSurface == NULL) { return -1; } /* Make sure surface size is the same. */ if ((surface->w != referenceSurface->w) || (surface->h != referenceSurface->h)) { return -2; } /* Sanitize input value */ if (allowable_error<0) { allowable_error = 0; } SDL_LockSurface( surface ); SDL_LockSurface( referenceSurface ); ret = 0; bpp = surface->format->BytesPerPixel; bpp_reference = referenceSurface->format->BytesPerPixel; /* Compare image - should be same format. */ for (j=0; j<surface->h; j++) { for (i=0; i<surface->w; i++) { p = (Uint8 *)surface->pixels + j * surface->pitch + i * bpp; p_reference = (Uint8 *)referenceSurface->pixels + j * referenceSurface->pitch + i * bpp_reference; SDL_GetRGBA(*(Uint32*)p, surface->format, &R, &G, &B, &A); SDL_GetRGBA(*(Uint32*)p_reference, referenceSurface->format, &Rd, &Gd, &Bd, &Ad); dist = 0; dist += (R-Rd)*(R-Rd); dist += (G-Gd)*(G-Gd); dist += (B-Bd)*(B-Bd); /* Allow some difference in blending accuracy */ if (dist > allowable_error) { ret++; } } } SDL_UnlockSurface( surface ); SDL_UnlockSurface( referenceSurface ); /* Save test image and reference for analysis on failures */ _CompareSurfaceCount++; if (ret != 0) { SDL_snprintf(imageFilename, 127, "CompareSurfaces%04d_TestOutput.bmp", _CompareSurfaceCount); SDL_SaveBMP(surface, imageFilename); SDL_snprintf(referenceFilename, 127, "CompareSurfaces%04d_Reference.bmp", _CompareSurfaceCount); SDL_SaveBMP(referenceSurface, referenceFilename); SDLTest_LogError("Surfaces from failed comparison saved as '%s' and '%s'", imageFilename, referenceFilename); } return ret; }
void DINGOOGUIWindowImp::prepareFonts() { Uint32 rmask, gmask, bmask, amask; Config *config=Config::GetInstance() ; unsigned char r,g,b ; const char *value=config->GetValue("BACKGROUND") ; if (value) { char2hex(value,&r) ; char2hex(value+2,&g) ; char2hex(value+4,&b) ; } else { r=0xFF ; g=0xFF ; b=0xFF ; } backgroundColor_=SDL_MapRGB(screen_->format, r,g,b) ; value=config->GetValue("FOREGROUND") ; if (value) { char2hex(value,&r) ; char2hex(value+2,&g) ; char2hex(value+4,&b) ; } else { r=0x00 ; g=0x00 ; b=0x00 ; } foregroundColor_=SDL_MapRGB(screen_->format, r,g,b) ; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif for (int i=0;i<FONT_COUNT;i++) { fonts[i] = SDL_CreateRGBSurface(SDL_HWSURFACE, 8, 8, 16, 0, 0, 0, 0); if (fonts[i]==NULL) { Trace::Dump("Failed to create font surface %d",i) ; } else { SDL_LockSurface(fonts[i]) ; const unsigned char *src=font+i*8 ; unsigned short*dest=(unsigned short *)fonts[i]->pixels ; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { *dest =(*src)?backgroundColor_:foregroundColor_; dest++; src++ ; } if (y<7) src+=FONT_WIDTH-8 ; } SDL_UnlockSurface(fonts[i]) ; } ; }; } ;
font * ttf_write_tga (char *name, int32_t pointsize) { uint32_t rmask, gmask, bmask, amask; double glyph_per_row; char filename[200]; SDL_Surface *dst; uint32_t height; uint32_t width; double maxx; double maxy[TTF_GLYPH_MAX]; uint32_t c; int x; int y; double h; font *f; snprintf(filename, sizeof(filename), "%s_pointsize%u.tga", name, pointsize); if (tex_find(filename)) { return (0); } /* * x glyphs horizontally and y vertically. */ glyph_per_row = 16; f = ttf_new(name, pointsize, TTF_STYLE_NORMAL); if (!f) { ERR("could not create font %s", name); } maxx = 0; memset(maxy, 0, sizeof(maxy)); /* * Find the largest font glyph pointsize. */ x = 0; y = 0; height = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { if (f->tex[c].image) { maxx = max(maxx, f->tex[c].image->w); maxy[y] = max(maxy[y], f->tex[c].image->h); } if (++x >= glyph_per_row) { x = 0; height += maxy[y]; y++; } } if (!maxx) { ERR("no glyphs in font %s", name); } width = glyph_per_row * maxx; if (MULTIPLE_BITS(width)) { width = nextpoweroftwo(width); } height += 40; if (MULTIPLE_BITS(height)) { height = nextpoweroftwo(height); } /* * Make a large surface for all glyphs. */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif dst = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); if (!dst) { ERR("no surface created for size %dx%d font %s", width, height, name); } newptr(dst, "SDL_CreateRGBSurface"); /* * Blit each glyph to the large surface. */ x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { if (f->tex[c].image) { SDL_Rect dstrect = { maxx * x, h, maxx, maxy[y] }; SDL_BlitSurface(f->tex[c].image, 0, dst, &dstrect); } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } /* * Convert the black border smoothing that ttf adds into alpha. */ { double x; double y; for (x = 0; x < dst->w; x++) { for (y = 0; y < dst->h; y++) { color c; c = getPixel(dst, x, y); if ((c.a == 255) && (c.r == 255) && (c.g == 255) && (c.b == 255)) { /* * Do nothing. */ } else if ((c.a == 0) && (c.r == 0) && (c.g == 0) && (c.b == 0)) { /* * Do nothing. */ } else { /* * Convery gray to white with alpha. */ c.a = (c.r + c.g + c.b) / 3; c.r = 255; c.g = 255; c.b = 255; } putPixel(dst, x, y, c); } } } #define MAX_TEXTURE_HEIGHT 4096 if (dst->h > MAX_TEXTURE_HEIGHT) { ERR("ttf is too large"); } uint8_t filled_pixel_row[MAX_TEXTURE_HEIGHT] = {0}; /* * What the hell am I doing here? The ttf library returns incorrect * boounds for the top and bottom of glyphs, so I'm looking for a line of * no pixels above and below each glyph so I can really find the texture * bounds of a glyph. This allows squeezing of text together. */ { int x; int y; for (y = 0; y < dst->h; y++) { for (x = 0; x < dst->w; x++) { color c; c = getPixel(dst, x, y); if (c.r || c.g || c.b || c.a) { filled_pixel_row[y] = true; break; } } } } /* * Work our the tex co-ords for each glyph in the large tex. */ x = 0; y = 0; h = 0; int d1_max = 0; int d2_max = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { { int y = (h + (h + f->glyphs[c].height)) / 2; int miny = y; int maxy = y; for (;;) { if (!filled_pixel_row[miny]) { break; } miny--; if (miny <= 0) { break; } } for (;;) { if (!filled_pixel_row[maxy]) { break; } maxy++; if (maxy >= MAX_TEXTURE_HEIGHT - 1) { break; } } int d1 = y - miny; if (d1 > d1_max) { d1_max = d1; } int d2 = maxy - y; if (d2 > d2_max) { d2_max = d2; } } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { f->glyphs[c].texMinX = (double)(x * maxx) / (double)dst->w; f->glyphs[c].texMaxX = (double)((x * maxx) + f->glyphs[c].width) / (double)dst->w; { int y = (h + (h + f->glyphs[c].height)) / 2; int y1 = y - d1_max; int y2 = y + d2_max; if (y1 < 0) { y1 = 0; } f->glyphs[c].texMinY = (double)(y1) / (double)dst->h; f->glyphs[c].texMaxY = (double)(y2) / (double)dst->h; } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } SDL_LockSurface(dst); stbi_write_tga(filename, dst->w, dst->h, STBI_rgb_alpha, dst->pixels); SDL_UnlockSurface(dst); texp tex; tex = tex_from_surface(dst, filename, filename); if (!tex) { ERR("could not convert %s to tex", filename); } /* * Work our the tex co-ords for each glyph in the large tex. */ x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { f->tex[c].image = dst; f->tex[c].tex = tex_get_gl_binding(tex); } /* * Save the glyph data. */ snprintf(filename, sizeof(filename), "%s_pointsize%u.data", name, pointsize); FILE *out = fopen(filename, "w"); fwrite(f->glyphs, sizeof(f->glyphs), 1, out); fclose(out); printf("wrote %s\n",filename); return (f); }
static DFBResult update_screen( int x, int y, int w, int h ) { #if 0 int i, n; void *dst; void *src; DFBResult ret; CoreSurface *surface; CoreSurfaceBuffer *buffer; CoreSurfaceBufferLock lock; u16 *src16, *dst16; u8 *src8; #endif D_DEBUG_AT( SDL_Updates, "%s( %d, %d, %d, %d )\n", __FUNCTION__, x, y, w, h ); D_DEBUG_AT( SDL_Updates, " -> locking sdl lock...\n" ); fusion_skirmish_prevail( &dfb_sdl->lock ); #if 0 surface = dfb_sdl->primary; D_MAGIC_ASSERT_IF( surface, CoreSurface ); D_DEBUG_AT( SDL_Updates, " -> primary is %p\n", surface ); if (!surface) { D_DEBUG_AT( SDL_Updates, " -> unlocking sdl lock...\n" ); fusion_skirmish_dismiss( &dfb_sdl->lock ); D_DEBUG_AT( SDL_Updates, " -> done.\n" ); return DFB_OK; } buffer = dfb_surface_get_buffer( surface, CSBR_FRONT ); D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); D_DEBUG_AT( SDL_Updates, " -> locking sdl surface...\n" ); if (SDL_LockSurface( screen ) < 0) { D_ERROR( "DirectFB/SDL: " "Couldn't lock the display surface: %s\n", SDL_GetError() ); fusion_skirmish_dismiss( &dfb_sdl->lock ); return DFB_FAILURE; } D_DEBUG_AT( SDL_Updates, " -> locking dfb surface...\n" ); ret = dfb_surface_buffer_lock( buffer, CSAF_CPU_READ, &lock ); if (ret) { D_ERROR( "DirectFB/SDL: Couldn't lock layer surface: %s\n", DirectFBErrorString( ret ) ); SDL_UnlockSurface(screen); fusion_skirmish_dismiss( &dfb_sdl->lock ); return ret; } src = lock.addr; dst = screen->pixels; src += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * lock.pitch; dst += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * screen->pitch; D_DEBUG_AT( SDL_Updates, " -> copying pixels...\n" ); switch (screen->format->BitsPerPixel) { case 16: dfb_convert_to_rgb16( surface->config.format, src, lock.pitch, surface->config.size.h, dst, screen->pitch, w, h ); break; default: direct_memcpy( dst, src, DFB_BYTES_PER_LINE( surface->config.format, w ) ); } D_DEBUG_AT( SDL_Updates, " -> unlocking dfb surface...\n" ); dfb_surface_buffer_unlock( &lock ); D_DEBUG_AT( SDL_Updates, " -> unlocking sdl surface...\n" ); SDL_UnlockSurface( screen ); #endif D_DEBUG_AT( SDL_Updates, " -> calling SDL_UpdateRect()...\n" ); SDL_UpdateRect( dfb_sdl->screen, x, y, w, h ); D_DEBUG_AT( SDL_Updates, " -> unlocking sdl lock...\n" ); fusion_skirmish_dismiss( &dfb_sdl->lock ); D_DEBUG_AT( SDL_Updates, " -> done.\n" ); return DFB_OK; }
/** * Unlocks the surface after it's been locked * to resume blitting operations. * @sa lock() */ void Surface::unlock() { SDL_UnlockSurface(_surface); }
void AntiFlicker(SDL_Surface *copyFrom, SDL_Surface *copyTo) { int i, j; uint8_t *s1, *s2, *sr; uint8_t *s1w, *s2w, *srw; if (SDL_MUSTLOCK(screen)) {if (SDL_LockSurface(screen) < 0) return;} if (SDL_MUSTLOCK(scrSurf[0])) {if (SDL_LockSurface(scrSurf[0]) < 0) return;} if (SDL_MUSTLOCK(scrSurf[1])) {if (SDL_LockSurface(scrSurf[1]) < 0) return;} if (doCopyOfSurfaces) { s1 = (uint8_t *)copyFrom->pixels; s2 = (uint8_t *)copyTo->pixels; for (i = HEIGHT; i--;) { uint32_t *s1dw = (uint32_t *)s1; uint32_t *s2dw = (uint32_t *)s2; for (j = WIDTH; j--;) { *(s2dw++) = *(s1dw++); } s1 += copyFrom->pitch; s2 += copyTo->pitch; } doCopyOfSurfaces = false; } sr = (uint8_t *)screen->pixels; s1 = (uint8_t *)scrSurf[0]->pixels; s2 = (uint8_t *)scrSurf[1]->pixels; for (i = HEIGHT; i--;) { srw = sr; s1w = s1; s2w = s2; for (j = WIDTH; j--;) { #if defined(ZEMU_BIG_ENDIAN) || defined(__APPLE__) *(srw++) = 0; s1w++; s2w++; #endif *srw = (uint8_t)(((unsigned int)(*s1w) + (unsigned int)(*s2w)) >> 1); srw++; s1w++; s2w++; *srw = (uint8_t)(((unsigned int)(*s1w) + (unsigned int)(*s2w)) >> 1); srw++; s1w++; s2w++; *srw = (uint8_t)(((unsigned int)(*s1w) + (unsigned int)(*s2w)) >> 1); srw++; s1w++; s2w++; #if !defined(ZEMU_BIG_ENDIAN) && !defined(__APPLE__) *(srw++) = 0; s1w++; s2w++; #endif } sr += screen->pitch; s1 += scrSurf[0]->pitch; s2 += scrSurf[1]->pitch; } if (SDL_MUSTLOCK(scrSurf[1])) SDL_UnlockSurface(scrSurf[1]); if (SDL_MUSTLOCK(scrSurf[0])) SDL_UnlockSurface(scrSurf[0]); if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); }
void CollideImage(SDL_Surface* src,int x,int y,int sx,int sy,int w,int h,int cm,int wm,char id) { if (x<0) x=0; if (y<0) y=0; if (x+w>640) w=640-x; if (y+h>479) h=479-y; int mc=SDL_MapRGB(src->format,255,0,255); for (int z=0;z<MAX_LAYERS;z++) { if (wm & (1<<z)) { if (collision_layer[z]) { SDL_LockSurface(src); SDL_LockSurface(collision_layer[z]); for (int ty=0;ty<h;ty++) { char* p2=(char*)collision_layer[z]->pixels; p2+=(y+ty)*collision_layer[z]->pitch+x; char* p1=(char*)src->pixels; p1+=((sy+ty)*src->pitch)+(sx*src->format->BytesPerPixel); for (int tx=0;tx<w;tx++) { int c=*p1 + (*(p1+1)<<8); if (c!=mc) *p2=id; p1++; p1++; p2++; } } SDL_UnlockSurface(src); SDL_UnlockSurface(collision_layer[z]); // printf("z %d\n",z); /*if (z==1) { SDL_Rect srcRect; srcRect.x = 0; srcRect.y = 0; srcRect.w = 640; srcRect.h = 480; SDL_Rect dstRect; dstRect.x = 0; dstRect.y = 0; dstRect.w = 640; dstRect.h = 480; SDL_BlitSurface(collision_layer[z], &srcRect, screen, &dstRect); }*/ } } } }
/** * Scale functions */ void scaleDynamic( SDL_Surface *srcSfc, SDL_Rect srGsRect, SDL_Surface *dstSfc, SDL_Rect dstRect ) { const bool equalWidth = (dstRect.w == srcSfc->w); const bool equalHeight = (dstRect.h == srcSfc->h); if(equalWidth && equalHeight) { SDL_Rect sdldstrect; sdldstrect.x = dstRect.x; sdldstrect.y = dstRect.y; sdldstrect.w = dstRect.w; sdldstrect.h = dstRect.h; assert(srcSfc); assert(dstSfc); BlitSurface(srcSfc, &srGsRect, dstSfc, &sdldstrect); return; } SDL_LockSurface( srcSfc ); SDL_LockSurface( dstSfc ); Uint32 *dstFirstPixel = static_cast<Uint32*>(dstSfc->pixels); Uint32 *srcFirstPixel = static_cast<Uint32*>(srcSfc->pixels); Uint32 *dstPixel = dstFirstPixel; Uint32 *srcPixel = srcFirstPixel; // Pass those numbers to the stack, they are used very often. const float wFac = (float(srcSfc->w)) / (float(dstRect.w)); const float hFac = (float(srcSfc->h)) / (float(dstRect.h)); int pitch = dstRect.y*dstSfc->w; if(pitch >= 0) dstPixel += pitch; if(dstRect.x >= 0) dstPixel += dstRect.x; if(dstRect.w > dstSfc->w) dstRect.w = dstSfc->w; if(dstRect.h > dstSfc->h) dstRect.h = dstSfc->h; float xSrc, ySrc; ySrc = 0.0f; //SDL_PixelFormat *format = srcSfc->format; if(equalWidth) { for( int yDst = 0 ; yDst<dstSfc->h ; yDst++ ) { const Uint32 posY = (yDst*srcSfc->h)/dstSfc->h; memcpy(dstPixel, srcPixel+(posY*dstSfc->w), srcSfc->pitch); dstPixel += dstSfc->w; } } else { for( int yDst = 0 ; yDst<dstRect.h ; yDst++ ) { xSrc = 0.0f; pitch = Uint32(ySrc)*srcSfc->w; for( int xDst = 0; xDst<dstRect.w ; xDst++ ) { *dstPixel = srcPixel[pitch+Uint32(xSrc)]; xSrc += wFac; dstPixel++; } ySrc += hFac; dstPixel = dstFirstPixel + (dstSfc->w*yDst); } } SDL_UnlockSurface( dstSfc ); SDL_UnlockSurface( srcSfc ); }
static VALUE Game_update_screen(VALUE self) { const Game* game; Data_Get_Struct(self, Game, game); CheckDisposed(game); volatile VALUE rbScreen = game->screen; const Texture* texture; Data_Get_Struct(rbScreen, Texture, texture); strb_CheckDisposedTexture(texture); const Pixel* src = texture->pixels; SDL_Surface* sdlScreenBuffer = game->sdlScreenBuffer; SDL_LockSurface(sdlScreenBuffer); Pixel* dst = (Pixel*)sdlScreenBuffer->pixels; const int screenPadding = sdlScreenBuffer->pitch / sdlScreenBuffer->format->BytesPerPixel - sdlScreenBuffer->w; const int textureWidth = texture->width; const int textureHeight = texture->height; const int heightPadding = sdlScreenBuffer->w - texture->width + screenPadding; for (int j = 0; j < textureHeight; j++, dst += heightPadding) { for (int i = 0; i < textureWidth; i++, src++, dst++) { const uint8_t alpha = src->color.alpha; if (alpha == 255) { *dst = *src; } else if (alpha) { dst->color.red = DIV255(src->color.red * alpha); dst->color.green = DIV255(src->color.green * alpha); dst->color.blue = DIV255(src->color.blue * alpha); } else { dst->color.red = 0; dst->color.green = 0; dst->color.blue = 0; } } } SDL_UnlockSurface(sdlScreenBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, sdlScreenBuffer->w, sdlScreenBuffer->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, sdlScreenBuffer->pixels); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glBegin(GL_QUADS); { int x1, y1, x2, y2; if (!game->isFullscreen) { x1 = 0; y1 = 0; x2 = game->sdlScreen->w; y2 = game->sdlScreen->h; } else { x1 = (game->sdlScreen->w - textureWidth) / 2; y1 = (game->sdlScreen->h - textureHeight) / 2; x2 = x1 + textureWidth; y2 = y1 + textureHeight; } const double tu = (double)textureWidth / sdlScreenBuffer->w; const double tv = (double)textureHeight / sdlScreenBuffer->h; glTexCoord2f(0.0, 0.0); glVertex3i(x1, y1, 0); glTexCoord2f(tu, 0.0); glVertex3i(x2, y1, 0); glTexCoord2f(tu, tv); glVertex3i(x2, y2, 0); glTexCoord2f(0.0, tv); glVertex3i(x1, y2, 0); } glEnd(); SDL_GL_SwapBuffers(); return Qnil; }
void I_InitGraphics(void) { SDL_Event dummy; byte *doompal; int flags = 0; char *env; // Pass through the XSCREENSAVER_WINDOW environment variable to // SDL_WINDOWID, to embed the SDL window into the Xscreensaver // window. env = getenv("XSCREENSAVER_WINDOW"); if (env != NULL) { char winenv[30]; int winid; sscanf(env, "0x%x", &winid); sprintf(winenv, "SDL_WINDOWID=%i", winid); putenv(winenv); } SetSDLVideoDriver(); if (SDL_Init(SDL_INIT_VIDEO) < 0) { I_Error("Failed to initialize video: %s", SDL_GetError()); } // Check for command-line video-related parameters. CheckCommandLine(); doompal = W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE); if (screensaver_mode) { windowwidth = 0; windowheight = 0; } else { if (autoadjust_video_settings) { I_AutoAdjustSettings(); } windowwidth = screen_width; windowheight = screen_height; screen_mode = I_FindScreenMode(windowwidth, windowheight); if (screen_mode == NULL) { I_Error("I_InitGraphics: Unable to find a screen mode small " "enough for %ix%i", windowwidth, windowheight); } if (windowwidth != screen_mode->width || windowheight != screen_mode->height) { printf("I_InitGraphics: %s (%ix%i within %ix%i)\n", WindowBoxType(screen_mode, windowwidth, windowheight), screen_mode->width, screen_mode->height, windowwidth, windowheight); } // Generate lookup tables before setting the video mode. if (screen_mode->InitMode != NULL) { screen_mode->InitMode(doompal); } } // Set up title and icon. Windows cares about the ordering; this // has to be done before the call to SDL_SetVideoMode. I_SetWindowCaption(); #if !SDL_VERSION_ATLEAST(1, 3, 0) I_SetWindowIcon(); #endif // Set the video mode. flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF; if (fullscreen) { flags |= SDL_FULLSCREEN; } screen = SDL_SetVideoMode(windowwidth, windowheight, 8, flags); if (screen == NULL) { I_Error("Error setting video mode: %s\n", SDL_GetError()); } // Start with a clear black screen // (screen will be flipped after we set the palette) if (SDL_LockSurface(screen) >= 0) { byte *screenpixels; int y; screenpixels = (byte *) screen->pixels; for (y=0; y<screen->h; ++y) memset(screenpixels + screen->pitch * y, 0, screen->w); SDL_UnlockSurface(screen); } // Set the palette I_SetPalette(doompal); SDL_SetColors(screen, palette, 0, 256); CreateCursors(); UpdateFocus(); UpdateGrab(); // In screensaver mode, now find a screen_mode to use. if (screensaver_mode) { screen_mode = I_FindScreenMode(screen->w, screen->h); if (screen_mode == NULL) { I_Error("I_InitGraphics: Unable to find a screen mode small " "enough for %ix%i", screen->w, screen->h); } // Generate lookup tables before setting the video mode. if (screen_mode->InitMode != NULL) { screen_mode->InitMode(doompal); } } // On some systems, it takes a second or so for the screen to settle // after changing modes. We include the option to add a delay when // setting the screen mode, so that the game doesn't start immediately // with the player unable to see anything. if (fullscreen && !screensaver_mode) { SDL_Delay(startup_delay); } // Check if we have a native surface we can use // If we have to lock the screen, draw to a buffer and copy // Likewise if the screen pitch is not the same as the width // If we have to multiply, drawing is done to a separate 320x200 buf native_surface = !SDL_MUSTLOCK(screen) && screen_mode == &mode_scale_1x && screen->pitch == SCREENWIDTH && aspect_ratio_correct; // If not, allocate a buffer and copy from that buffer to the // screen when we do an update if (native_surface) { screens[0] = (unsigned char *) screen->pixels; screens[0] += (screen->h - SCREENHEIGHT) / 2; } else { screens[0] = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL); } // "Loading from disk" icon LoadDiskImage(); // Clear the screen to black. memset(screens[0], 0, SCREENWIDTH * SCREENHEIGHT); // We need SDL to give us translated versions of keys as well SDL_EnableUNICODE(1); // Repeat key presses - this is what Vanilla Doom does // Not sure about repeat rate - probably dependent on which DOS // driver is used. This is good enough though. SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // clear out any events waiting at the start and center the mouse while (SDL_PollEvent(&dummy)); if (usemouse && !nomouse && (fullscreen || grabmouse)) { CenterMouse(); } initialized = true; }
BCPLWORD sdlfn(BCPLWORD *a, BCPLWORD *g, BCPLWORD *W) { char tmpstr[256]; //printf("sdlfn: fno=%d a1=%d a2=%d a3=%d a4=%d\n", // a[0], a[1], a[2], a[3], a[4]); switch(a[0]) { default: printf("sdlfn: Unknown op: fno=%d a1=%d a2=%d a3=%d a4=%d\n", a[0], a[1], a[2], a[3], a[4]); return 0; case sdl_avail: // Test whether SDL is available return -1; // SDL is available case gl_avail: // Test whether OpenGL is available #ifdef GLavail return -1; // OpenGL is available #else return 0; // OpenGL is not available #endif case sdl_init: // Initialise all SDL features { BCPLWORD res = (BCPLWORD) SDL_Init(SDL_INIT_EVERYTHING); // Enable Unicode translation of keyboard events. SDL_EnableUNICODE(1); SDL_JoystickEventState(SDL_ENABLE); //printf("sdl_init\n"); return res; } case sdl_setvideomode: // width, height, bbp, flags { SDL_Surface *scr; //printf("Calling SetVideoMode(%d, %d, %d, %8x)\n", a[1], a[2], a[3], a[4]); scr = SDL_SetVideoMode((int)a[1], (int)a[2], (int)a[3], (Uint32)a[4]); SDL_Flip(scr); return (BCPLWORD) scr; //return (BCPLWORD) SDL_SetVideoMode((int)a[1], (int)a[2], (int)a[3], (Uint32)a[4]); } case sdl_quit: // Shut down SDL printf("sdl_quit\n"); SDL_Quit(); return -1; case sdl_locksurface: // surf // Return 0 on success // Return -1 on failure return (BCPLWORD) SDL_LockSurface((SDL_Surface*) a[1]); case sdl_unlocksurface: // surf SDL_UnlockSurface((SDL_Surface*) a[1]); return 0; case sdl_getsurfaceinfo: // surf, surfinfo -> [flag, format, w, h, pitch, pixels, cliprect, refcount] { SDL_Surface *surf = (SDL_Surface*)a[1]; BCPLWORD *info = &W[a[2]]; info[ 0] = (BCPLWORD) (surf->flags); info[ 1] = (BCPLWORD) (surf->format); info[ 2] = (BCPLWORD) (surf->w); info[ 3] = (BCPLWORD) (surf->h); info[ 4] = (BCPLWORD) (surf->pitch); info[ 5] = (BCPLWORD) (surf->pixels); //info[ 6] = (BCPLWORD) (surf->clip_rect); // fields: x,y, w, h info[ 7] = (BCPLWORD) (surf->refcount); //printf("getsurfaceinfo: format=%d\n", info[1]); return 0; } case sdl_getfmtinfo: // fmt, pxlinfo -> [palette, bitspp, bytespp, rmask, gmask, rmask, amask, // rloss, rshift, gloss, gshift, bloss, bshift, aloss, ashift, // colorkey, alpha] { SDL_PixelFormat *fmt = (SDL_PixelFormat*)(a[1]); BCPLWORD *info = &(W[a[2]]); //printf("getfmtinfo: format=%d\n", (BCPLWORD)fmt); info[ 0] = (BCPLWORD) (fmt->palette); info[ 1] = (BCPLWORD) (fmt->BitsPerPixel); info[ 2] = (BCPLWORD) (fmt->BytesPerPixel); info[ 3] = (BCPLWORD) (fmt->Rmask); info[ 4] = (BCPLWORD) (fmt->Gmask); info[ 5] = (BCPLWORD) (fmt->Bmask); info[ 6] = (BCPLWORD) (fmt->Amask); info[ 7] = (BCPLWORD) (fmt->Rshift); info[ 8] = (BCPLWORD) (fmt->Gshift); info[ 9] = (BCPLWORD) (fmt->Bshift); info[10] = (BCPLWORD) (fmt->Ashift); info[11] = (BCPLWORD) (fmt->Rloss); info[12] = (BCPLWORD) (fmt->Gloss); info[13] = (BCPLWORD) (fmt->Rloss); info[14] = (BCPLWORD) (fmt->Aloss); info[15] = (BCPLWORD) (fmt->colorkey); info[16] = (BCPLWORD) (fmt->alpha); return 0; } case sdl_geterror: // str -- fill str with BCPL string for the latest SDL error { char *str = SDL_GetError(); printf("sdl_geterror: %s\n", str); return c2b_str(str, a[1]); // Convert to BCPL string format } case sdl_updaterect: // surf, left, top, right, bottom return 0; // Not yet available case sdl_loadbmp: // filename of a .bmp image { char tmpstr[256]; b2c_str(a[1], tmpstr); return (BCPLWORD) SDL_LoadBMP(tmpstr); } case sdl_mksurface: //(format, w, h) { SDL_PixelFormat *fmt = (SDL_PixelFormat*)(a[1]); Uint32 rmask = fmt->Rmask; Uint32 gmask = fmt->Gmask; Uint32 bmask = fmt->Bmask; Uint32 amask = fmt->Amask; //printf("rmask=%8x gmask=%8x bmask=%8x amask=%8x\n", rmask, gmask, bmask, amask); return (BCPLWORD)SDL_CreateRGBSurface( SDL_SWSURFACE, a[2], a[3], // Width, Height 32, // Not using a palette rmask, gmask, bmask, amask); } case sdl_blitsurface: // src, srcrect, dest, destrect //printf("blitsurface: %d, %d, %d, %d)\n", a[1], a[2], a[3], a[4]); { BCPLWORD *p = &W[a[4]]; SDL_Rect dstrect = {p[0],p[1],p[2],p[3]}; //printf("x=%d, y=%d, w=%d, h=%d\n", p[0], p[1], p[2], p[3]); return (BCPLWORD) SDL_BlitSurface((SDL_Surface*) a[1], (SDL_Rect*) 0, (SDL_Surface*) a[3], &dstrect); } case sdl_setcolourkey: //(surf, key) // If key=-1 unset colour key // otherwise set colour key to given value. // key must be in the pixel format of the given surface //printf("sdl_setcolourkey: %8x\n", a[2]); if(a[2]==-1) { return (BCPLWORD)SDL_SetColorKey((SDL_Surface*)a[1], 0, (Uint32)a[2]); } else { return (BCPLWORD)SDL_SetColorKey((SDL_Surface*)a[1], SDL_SRCCOLORKEY, (Uint32)a[2]); } case sdl_freesurface: // surf SDL_FreeSurface((SDL_Surface*)a[1]); return 0; case sdl_setalpha: // surf, flags, alpha return 0; // Not yet available case sdl_imgload: // filename -- using the SDL_image library return 0; // Not yet available case sdl_delay: // msecs -- the SDL delay function SDL_Delay((int)a[1]); return 0; case sdl_getticks: // return msecs since initialisation return (BCPLWORD)SDL_GetTicks(); case sdl_showcursor: // Show the cursor return (BCPLWORD)SDL_ShowCursor(SDL_ENABLE); case sdl_hidecursor: // Hide the cursor return (BCPLWORD)SDL_ShowCursor(SDL_DISABLE); case sdl_flip: // surf -- Double buffered update of the screen return (BCPLWORD) SDL_Flip((SDL_Surface*)a[1]); case sdl_displayformat: // surf -- convert surf to display format return 0; // Not yet available case sdl_waitevent: // (pointer) to [type, args, ... ] to hold details of the next event // return 0 if no events available return 0; // Not yet available case sdl_pollevent: // (pointer) to [type, args, ... ] to hold details of // the next event { SDL_Event test_event; if (SDL_PollEvent(&test_event)) { decodeevent(&test_event, &W[a[1]]); return -1; } decodeevent(0, &W[a[1]]); return 0; } case sdl_getmousestate: // pointer to [x, y] returns bit pattern of buttons currently pressed return 0; // Not yet available case sdl_loadwav: // file, spec, buff, len return 0; // Not yet available case sdl_freewav: // buffer return 0; // Not yet available case sdl_wm_setcaption: // surf, string { char tmpstr[256]; b2c_str(a[1], tmpstr); SDL_WM_SetCaption(tmpstr, 0); return 0; } case sdl_videoinfo: // buffer { const SDL_VideoInfo* p = SDL_GetVideoInfo(); BCPLWORD *info = &W[a[1]]; info[ 0] = (BCPLWORD) ((p->hw_available) | (p->hw_available)<<1 | (p->blit_hw)<<2 | (p->blit_hw_CC)<<3 | (p->blit_hw_A)<<4 | (p->blit_sw)<<5 | (p->blit_sw_CC)<<6 | (p->blit_sw_A)<<7 ); info[ 1] = (BCPLWORD) (p->blit_fill); info[ 2] = (BCPLWORD) (p->video_mem); info[ 3] = (BCPLWORD) (p->vfmt); info[ 4] = (BCPLWORD) (p->vfmt->BitsPerPixel); //printf("videoinfo: a[2]=%d %8X %8X %d %d %d\n", // a[2], info[0], info[1], info[2], info[3], info[4]); return 0; } case sdl_maprgb: // format, r, g, b { return (BCPLWORD) SDL_MapRGB((SDL_PixelFormat*)(a[1]), a[2], a[3], a[4]); } case sdl_drawline: { SDL_Surface *surf = (SDL_Surface*)(a[1]); //printf("\nDraw Line: %d %d %d %d %d %8x\n", a[1], a[2], a[3], a[4], a[5], a[6]); Draw_Line(surf, a[2], a[3], a[4], a[5], a[6]); return 0; } case sdl_drawhline: case sdl_drawvline: case sdl_drawcircle: case sdl_drawrect: case sdl_drawpixel: case sdl_drawellipse: case sdl_drawfillellipse: case sdl_drawround: case sdl_drawfillround: return 0; case sdl_drawfillcircle: { SDL_Surface *surf = (SDL_Surface*)(a[1]); Draw_FillCircle(surf, a[2], a[3], a[4], a[5]); return 0; } // case sdl_drawfillrect: //return Draw_FillRect((SDL_Surface*)a[1], 500,200, 50,70, 0xF0FF00); case sdl_fillrect: { SDL_Rect rect = {a[2],a[3],a[4],a[5]}; //printf("\nfillrect: surface=%d rect=(%d,%d,%d,%d) col=%8x\n", // a[1], a[2], a[3], a[4], a[5], a[6]); SDL_FillRect((SDL_Surface*)(a[1]), &rect, a[6]); return 0; } case sdl_fillsurf: //printf("\nfillsurf: surface=%d col=%8x\n", // a[1], a[2]); SDL_FillRect((SDL_Surface*)(a[1]), 0, a[2]); return 0; // Joystick functions case sdl_numjoysticks: return SDL_NumJoysticks(); case sdl_joystickopen: // 42 (index) => joy return (BCPLWORD)SDL_JoystickOpen(a[1]); case sdl_joystickclose: // 43 (joy) SDL_JoystickClose((SDL_Joystick *)a[1]); return 0; case sdl_joystickname: // 44 (index) { const char *name = SDL_JoystickName(a[1]); return c2b_str(name, a[1]); } case sdl_joysticknumaxes: // 45 (joy) return SDL_JoystickNumAxes((SDL_Joystick*)a[1]); case sdl_joysticknumbuttons: // 46 (joy) return SDL_JoystickNumButtons((SDL_Joystick*)a[1]); case sdl_joysticknumballs: // 47 (joy) return SDL_JoystickNumBalls((SDL_Joystick*)a[1]); case sdl_joysticknumhats: // 47 (joy) return SDL_JoystickNumHats((SDL_Joystick*)a[1]); case sdl_joystickeventstate: //49 sdl_enable=1 or sdl_ignore=0 return SDL_JoystickEventState(a[1]); case sdl_joystickgetbutton: // 55 (joy) return SDL_JoystickGetButton((SDL_Joystick*)a[1], a[2]); case sdl_joystickgetaxis: // 56 (joy) return SDL_JoystickGetAxis((SDL_Joystick*)a[1], a[2]); case sdl_joystickgethat: // 58 (joy) return SDL_JoystickGetHat((SDL_Joystick*)a[1], a[2]); case gl_setvideomode: // 200 (width, height) { // Setup minimum bit sizes, a depth buffer and double buffering. const SDL_VideoInfo* info = NULL; int bpp = 0; SDL_Surface *scr; info = SDL_GetVideoInfo(); if(!info) return 0; bpp = info->vfmt->BitsPerPixel; printf("bpp=%d width=%d height=%d\n", bpp, a[1], a[2]); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); printf("Calling SDL_SetVideoMode\n"); scr = SDL_SetVideoMode((int)a[1], (int)a[2], bpp, SDL_OPENGL); return (BCPLWORD)scr; } #ifdef GLavail case gl_ShadeModel: //printf("gl_ShadeModel: a[1]=%d GL_SMOOTH=%d\n", a[1], GL_SMOOTH); //glShadeModel((int)a[1]); //glShadeModel(GL_SMOOTH); return 0; case gl_CullFace: //printf("gl_CullFace: %d GL_BACK=%d\n", a[1], GL_BACK); //glCullFace(a[1]); //glCullFace(GL_BACK); return 0; case gl_FrontFace: //printf("gl_FrontFace: %d\n", a[1]); //printf(" GL_CCW=%d\n", GL_CCW); //glFrontFace(a[1]); //glFrontFace(GL_CCW); return 0; case gl_Enable: //printf("gl_Enable: %d\n", a[1]); //printf(" GL_CULLFACE=%d\n", GL_CULL_FACE); glEnable(a[1]); return 0; case gl_ClearColor: //printf("gl_ClearColor: %d %d %d %d\n", a[1], a[2], a[3], a[4]); glClearColor(a[1]/255.0, a[2]/255.0, a[3]/255.0, a[4]/255.0); return 0; case gl_ViewPort: printf("sdlfn: gl_Viewport: %d %d %d %d\n", a[1], a[2], a[3], a[4]); glViewport(a[1], a[2], a[3], a[4]); //glViewport(0, 0, 800, 500); return 0; case gl_MatrixMode: //printf("gl_MatrixMode: %d\n", a[1]); //printf(" GL_PROJECTION=%d\n", GL_PROJECTION); //printf(" GL_MODELVIEW=%d\n", GL_MODELVIEW); glMatrixMode(a[1]); return 0; case gl_LoadIdentity: //printf("gl_LoadIdentity:\n"); glLoadIdentity(); return 0; case glu_Perspective: //printf("gl_Perspective: %d %d %d %d\n", a[1], a[2], a[3], a[4]); //gluPerspective(((float)a[1])/1000000, ((float)a[2])/1000000, // ((float)a[3])/1000, ((float)a[4])/1000); //gluPerspective(60.0, 800.0/500.0, 1.0, 1024.0); return 0; case gl_Clear: //printf("gl_Clear: #x%8X\n", a[1]); //printf(" GL_COLOR_BUFFER_BIT=%8X\n", GL_COLOR_BUFFER_BIT); //printf(" GL_DEPTH_BUFFER_BIT=%8X\n", GL_DEPTH_BUFFER_BIT); glClear(a[1]); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); return 0; case gl_Translate: //printf("gl_Translate: %d %d %d\n", a[1], a[2], a[3]); glTranslatef(a[1]/1000.0, a[2]/1000.0, a[3]/1000.0); return 0; case gl_Rotate: //printf("gl_Rotate: %d %d %d %d\n", a[1], a[2], a[3], a[4]); glRotatef(a[1]/1000000.0, a[2]/1000.0, a[3]/1000.0, a[4]/1000.0); return 0; case gl_Begin: //printf("gl_Begin: %d\n", a[1]); //printf(" GL_TRIANGLES=%d\n", GL_TRIANGLES); glBegin(a[1]); return 0; case gl_End: //printf("gl_End:\n"); glEnd(); return 0; case gl_Color4v: //printf("gl_Color4v: %d\n", a[1]); glColor4ub(W[a[1]], W[a[1]+1], W[a[1]+2], W[a[1]+3]); return 0; case gl_Vertex3v: //printf("gl_Vertex3v: %d -> [%d %d %d]\n", a[1], W[a[1]], W[a[1]+1], W[a[1]+2]); glVertex3f(W[a[1]]/1000.0, W[a[1]+1]/1000.0, W[a[1]+2]/1000.0); return 0; case gl_SwapBuffers: //printf("gl_SwapBuffers:\n"); SDL_GL_SwapBuffers(); return 0; #endif // more to come ... } }
// Draw a string in the specified font void BaseEngine::DrawString(int iX, int iY, const char* pText, unsigned int uiColour, Font* pFont, SDL_Surface* pTarget ) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( pFont == NULL ) pFont = g_pMainFont; if ( m_bInsideDraw ) if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); SDL_Color color = { (uiColour&0xff0000)>>16, (uiColour&0xff00)>>8, (uiColour&0xff), 0 }; if ( ( pFont != NULL ) && ( pFont->GetFont() != NULL ) ) { SDL_Surface *sText = TTF_RenderText_Solid( pFont->GetFont(), pText, color ); SDL_Rect rcDest = {iX,iY,0,0}; SDL_BlitSurface( sText, NULL, pTarget, &rcDest ); SDL_FreeSurface( sText ); } if ( m_bInsideDraw ) if (SDL_MUSTLOCK(m_pActualScreen)) SDL_LockSurface(m_pActualScreen); } // Draw a triangle, as two vertical sided regions. void BaseEngine::DrawTriangle( double fX1, double fY1, double fX2, double fY2, double fX3, double fY3, unsigned int uiColour, SDL_Surface* pTarget ) { if ( pTarget == NULL ) pTarget = m_pActualScreen; // Ensure order is 1 2 3 from left to right if ( fX1 > fX2 ) { Swap( fX1,fX2 ); Swap( fY1,fY2 ); } // Bigger of 1 and 2 is in position 2 if ( fX2 > fX3 ) { Swap( fX2,fX3 ); Swap( fY2,fY3 ); } // Bigger of new 2 and 3 is in position 3 if ( fX1 > fX2 ) { Swap( fX1,fX2 ); Swap( fY1,fY2 ); } // Bigger of 1 and new 2 is in position 2 if ( fX1 == fX2 ) DrawVerticalSidedRegion( fX1, fX3, fY1, fY3, fY2, fY3, uiColour, pTarget ); else if ( fX2 == fX3 ) DrawVerticalSidedRegion( fX1, fX3, fY1, fY2, fY1, fY3, uiColour, pTarget ); else { // Split into two triangles. Find position on line 1-3 to split at double dSplitPointY = (double)fY1 + ( ( (double)((fX2-fX1)*(fY3-fY1)) ) / (double)(fX3-fX1) ); DrawVerticalSidedRegion( fX1, fX2, fY1, fY2, fY1, dSplitPointY, uiColour, pTarget ); DrawVerticalSidedRegion( fX2, fX3, fY2, fY3, dSplitPointY, fY3, uiColour, pTarget ); } } // Draw a vertical sided region. // If two points are the same then it is a triangle. // To do an arbitrary triangle, just draw two next to each other, one for left and one for right. void BaseEngine::DrawVerticalSidedRegion( double fX1, double fX2,// X positions double fY1a, double fY2a, // Start y positions for x1 and x2 double fY1b, double fY2b, // End y positions for x1 and x2 unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; // Ensure X1< X2, otherwise steps will go wrong! // Switch the points if x and y are wrong way round if ( fX2< fX1 ) { Swap(fX1,fX2); Swap(fY1a,fY2a); Swap(fY1b,fY2b); } int iXStart = (int)(fX1+0.5); int iXEnd = (int)(fX2+0.5); // If integer x positions are the same then avoid floating point inaccuracy problems by a special case if ( iXStart == iXEnd ) { int iYStart = (int)(fY1a+0.5); int iYEnd = (int)(fY2a+0.5); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iXStart, iY, uiColour, pTarget ); } else { // Draw left hand side int iYStart = (int)(fY1a+0.5); int iYEnd = (int)(fY1b+0.5); if ( iYStart> iYEnd ) Swap( iYStart, iYEnd ); //printf( "Firstline %d to %d (%f to %f)\n", iYStart, iYEnd, fY1a, fY1b ); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iXStart, iY, uiColour, pTarget ); // Draw the middle for ( int iX = iXStart+1 ; iX< iXEnd ; iX++ ) { double fYStart = fY1a + ( (((double)iX)-fX1)*(fY2a-fY1a)) /(fX2-fX1); double fYEnd = fY1b + ((((double)iX)-fX1)*(fY2b-fY1b))/(fX2-fX1); if ( fYEnd< fYStart ) Swap( fYStart, fYEnd ); int iYStart = (int)(fYStart+0.5); int iYEnd = (int)(fYEnd+0.5); //printf( "Line from %d to %d (%f to %f)\n", iYStart, iYEnd, fYStart, fYEnd ); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iX, iY, uiColour, pTarget ); } // Draw right hand side iYStart = (int)(fY2a+0.5); iYEnd = (int)(fY2b+0.5); if ( iYStart> iYEnd ) Swap( iYStart, iYEnd ); //printf( "Last line %d to %d (%f to %f)\n", iYStart, iYEnd, fY2a, fY2b ); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iXEnd, iY, uiColour, pTarget ); } } // Draw a rectangle on the specified surface void BaseEngine::DrawRectangle(int iX1, int iY1, int iX2, int iY2, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iX2 < iX1 ) { int t = iX1; iX1 = iX2; iX2 = t; } if ( iY2 < iY1 ) { int t = iY1; iY1 = iY2; iY2 = t; } for ( int iX = iX1 ; iX <= iX2 ; iX++ ) for ( int iY = iY1 ; iY <= iY2 ; iY++ ) SafeSetPixel( iX, iY, uiColour, pTarget ); } // Draw an oval on the specified surface void BaseEngine::DrawOval(int iX1, int iY1, int iX2, int iY2, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iX2 < iX1 ) { int t = iX1; iX1 = iX2; iX2 = t; } if ( iY2 < iY1 ) { int t = iY1; iY1 = iY2; iY2 = t; } double fCentreX = ((double)(iX2+iX1))/2.0; double fCentreY = ((double)(iY2+iY1))/2.0; double fXFactor = (double)((iX2-iX1) * (iX2-iX1))/4.0; double fYFactor = (double)((iY2-iY1) * (iY2-iY1))/4.0; double fDist; for ( int iX = iX1 ; iX <= iX2 ; iX++ ) for ( int iY = iY1 ; iY <= iY2 ; iY++ ) { fDist = ((double)iX - fCentreX) * ((double)iX - fCentreX)/fXFactor + ((double)iY - fCentreY) * ((double)iY - fCentreY)/fYFactor; if ( fDist <= 1.0 ) SafeSetPixel( iX, iY, uiColour, pTarget ); } } // Draw an oval on the specified surface void BaseEngine::DrawHollowOval( int iX1, int iY1, int iX2, int iY2, int iX3, int iY3, int iX4, int iY4, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iX2 < iX1 ) Swap( iX1, iX2 ); if ( iY2 < iY1 ) Swap( iY1, iY2 ); if ( iX4 < iX3 ) Swap( iX3, iX4 ); if ( iY4 < iY3 ) Swap( iY3, iY4 ); double fCentreX1 = ((double)(iX2+iX1))/2.0; double fCentreY1 = ((double)(iY2+iY1))/2.0; double fXFactor1 = (double)((iX2-iX1) * (iX2-iX1))/4.0; double fYFactor1 = (double)((iY2-iY1) * (iY2-iY1))/4.0; double fCentreX2 = ((double)(iX4+iX3))/2.0; double fCentreY2 = ((double)(iY4+iY3))/2.0; double fXFactor2 = (double)((iX4-iX3) * (iX4-iX3))/4.0; double fYFactor2 = (double)((iY4-iY3) * (iY4-iY3))/4.0; double fDist1, fDist2; for ( int iX = iX1 ; iX <= iX2 ; iX++ ) for ( int iY = iY1 ; iY <= iY2 ; iY++ ) { fDist1 = ((double)iX - fCentreX1) * ((double)iX - fCentreX1)/fXFactor1 + ((double)iY - fCentreY1) * ((double)iY - fCentreY1)/fYFactor1; fDist2 = ((double)iX - fCentreX2) * ((double)iX - fCentreX2)/fXFactor2 + ((double)iY - fCentreY2) * ((double)iY - fCentreY2)/fYFactor2; if ( ( fDist1 <= 1.0 ) && ( fDist2 >= 1.0 ) ) SafeSetPixel( iX, iY, uiColour, pTarget ); } } // Draw a line on the specified surface void BaseEngine::DrawLine(double fX1, double fY1, double fX2, double fY2, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; int iX1 = (int)(fX1+0.5); int iX2 = (int)(fX2+0.5); int iY1 = (int)(fY1+0.5); int iY2 = (int)(fY2+0.5); int iSteps = (iX2-iX1); if ( iSteps < 0 ) iSteps = -iSteps; if ( iY2 > iY1 ) iSteps += (iY2-iY1); else iSteps += (iY1-iY2); iSteps+=2; double fXStep = ((double)(fX2-fX1))/iSteps; double fYStep = ((double)(fY2-fY1))/iSteps; for ( int i = 0 ; i <= iSteps ; i++ ) { SafeSetPixel( (int)(0.5 + fX1 + fXStep*i), (int)(0.5 + fY1 + fYStep*i), uiColour, pTarget ); } } // Draw a thick line on the specified surface void BaseEngine::DrawThickLine( double fX1, double fY1, double fX2, double fY2, unsigned int uiColour, int iThickness, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iThickness < 2 ) { // Go to the quicker draw function DrawLine(fX1, fY1, fX2, fY2, uiColour, pTarget); return; } double fAngle1 = GetAngle( fX1, fY1, fX2, fY2 ); double fAngle1a = fAngle1 - ((5 * M_PI) / 4.0); double fAngle1b = fAngle1 + ((5 * M_PI) / 4.0); double fRectX1 = fX1 + iThickness * cos(fAngle1a) * 0.5; double fRectY1 = fY1 + iThickness * sin(fAngle1a) * 0.5; double fRectX2 = fX1 + iThickness * cos(fAngle1b) * 0.5; double fRectY2 = fY1 + iThickness * sin(fAngle1b) * 0.5; double fAngle2 = fAngle1 + M_PI; double fAngle2a = fAngle2 - ((5 * M_PI) / 4.0); double fAngle2b = fAngle2 + ((5 * M_PI) / 4.0); double fRectX3 = fX2 + iThickness * cos(fAngle2a) * 0.5; double fRectY3 = fY2 + iThickness * sin(fAngle2a) * 0.5; double fRectX4 = fX2 + iThickness * cos(fAngle2b) * 0.5; double fRectY4 = fY2 + iThickness * sin(fAngle2b) * 0.5; DrawTriangle( fRectX1, fRectY1, fRectX2, fRectY2, fRectX3, fRectY3, uiColour, pTarget ); DrawTriangle( fRectX3, fRectY3, fRectX4, fRectY4, fRectX1, fRectY1, uiColour, pTarget ); } // Draw a polygon on the specified surface void BaseEngine::DrawPolygon( int iPoints, double* pXArray, double* pYArray, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iPoints == 1 ) { SafeSetPixel( pXArray[0], pYArray[0], uiColour, pTarget ); return; } if ( iPoints == 2 ) { DrawLine( pXArray[0], pYArray[0], pXArray[1], pYArray[1], uiColour, pTarget ); return; } /* if ( iPoints == 3 ) { printf( "Draw triangle for points 0, 1, 2 of %d available\n", iPoints ); DrawTriangle( pXArray[0], pYArray[0], pXArray[1], pYArray[1], pXArray[2], pYArray[2], uiColour, pTarget ); return; } */ // Otherwise attempt to eliminate a point by filling the polygon, then call this again double fXCentre, fYCentre; //fX1, fX2, fX3, fY1, fY2, fY3; int i2, i3; double fAngle1, fAngle2, fAngle3; for ( int i1 = 0 ; i1 < iPoints ; i1++ ) { i2 = i1 + 1; if ( i2 >= iPoints ) i2 -= iPoints; i3 = i1 + 2; if ( i3 >= iPoints ) i3 -= iPoints; fXCentre = (pXArray[i1] + pXArray[i2] + pXArray[i3]) / 3.0; fYCentre = (pYArray[i1] + pYArray[i2] + pYArray[i3]) / 3.0; fAngle1 = GetAngle( fXCentre, fYCentre, pXArray[i1], pYArray[i1] ); fAngle2 = GetAngle( fXCentre, fYCentre, pXArray[i2], pYArray[i2] ); fAngle3 = GetAngle( fXCentre, fYCentre, pXArray[i3], pYArray[i3] ); // Now work out the relative angle positions and make sure all are positive fAngle2 -= fAngle1; if ( fAngle2 < 0 ) fAngle2 += 2*M_PI; fAngle3 -= fAngle1; if ( fAngle3 < 0 ) fAngle3 += 2*M_PI; if ( fAngle2 < fAngle3 ) { // Then points are in clockwise order so central one can be eliminated as long as we don't // fill an area that we shouldn't bool bPointIsWithinTriangle = false; if ( iPoints > 3 ) { // Need to check that there isn't a point within the area - for convex shapes double fLineAngle12 = GetAngle( pXArray[i1], pYArray[i1], pXArray[i2], pYArray[i2] ); if ( fLineAngle12 < 0 ) fLineAngle12 += M_PI * 2.0; double fLineAngle23 = GetAngle( pXArray[i2], pYArray[i2], pXArray[i3], pYArray[i3] ); if ( fLineAngle23 < 0 ) fLineAngle23 += M_PI * 2.0; double fLineAngle31 = GetAngle( pXArray[i3], pYArray[i3], pXArray[i1], pYArray[i1] ); if ( fLineAngle31 < 0 ) fLineAngle31 += M_PI * 2.0; for ( int i = i3+1 ; i != i1 ; i++ ) { if ( i >= iPoints ) { i = 0; if ( i1 == 0 ) break; // From the for loop - finished } // Otherwise we need to work out whether point i is to right of line i3 to i1 double fPointAngle1 = GetAngle( pXArray[i1], pYArray[i1], pXArray[i], pYArray[i] ); if ( fPointAngle1 < 0 ) fPointAngle1 += M_PI * 2.0; fPointAngle1 -= fLineAngle12; if ( fPointAngle1 < 0 ) fPointAngle1 += M_PI * 2.0; double fPointAngle2 = GetAngle( pXArray[i2], pYArray[i2], pXArray[i], pYArray[i] ); if ( fPointAngle2 < 0 ) fPointAngle2 += M_PI * 2.0; fPointAngle2 -= fLineAngle23; if ( fPointAngle2 < 0 ) fPointAngle2 += M_PI * 2.0; double fPointAngle3 = GetAngle( pXArray[i3], pYArray[i3], pXArray[i], pYArray[i] ); if ( fPointAngle3 < 0 ) fPointAngle3 += M_PI * 2.0; fPointAngle3 -= fLineAngle31; if ( fPointAngle3 < 0 ) fPointAngle3 += M_PI * 2.0; if ( ( fPointAngle1 < M_PI ) && ( fPointAngle2 < M_PI ) && ( fPointAngle3 < M_PI ) ) bPointIsWithinTriangle = true; } } if ( !bPointIsWithinTriangle ) {// If not then try the next position printf( "Draw for points %d, %d, %d of %d available\n", i1, i2, i3, iPoints ); DrawTriangle( pXArray[i1], pYArray[i1], pXArray[i2], pYArray[i2], pXArray[i3], pYArray[i3], /*GetColour(iPoints)*/uiColour, pTarget ); // Remove the point i2 and then recurse for ( int i = i2 ; i < (iPoints-1) ; i++ ) { printf( "\tCopy point %d to %d\n", i+1, i ); pXArray[i] = pXArray[i+1]; pYArray[i] = pYArray[i+1]; } if ( iPoints > 3 ) DrawPolygon( iPoints - 1, pXArray, pYArray, uiColour, pTarget ); return; // Done } } } } /* Added in 2014 since it was used in the GroundMovement playback program so may be useful elsewhere too, but students can ignore this */ void BaseEngine::DrawShortenedArrow( int iX1,int iY1,int iX2,int iY2, int iShortenedStart,int iShortenedEnd, unsigned int uiColour,int iThickness, int iHeadSize,SDL_Surface* pTarget ) { if ( pTarget == NULL ) pTarget = m_pActualScreen; //iShortenedStart += 10; // Test //iShortenedEnd += 10; // Test double dAngle1 = GetAngle( iX1,iY1,iX2,iY2 ); double dAngle2 = dAngle1 + M_PI; double dX1 = iX1 + iShortenedStart * cos( dAngle1 ); double dY1 = iY1 + iShortenedStart * sin( dAngle1 ); double dX2 = iX2 + iShortenedEnd * cos( dAngle2 ); double dY2 = iY2 + iShortenedEnd * sin( dAngle2 ); // First draw the line if ( iThickness < 2 ) { // Go to the quicker draw function DrawLine( dX1,dY1,dX2,dY2,uiColour,pTarget ); } else { double dX1l = iX1 + iShortenedStart * cos( dAngle1 ); double dY1l = iY1 + iShortenedStart * sin( dAngle1 ); double dX2l = iX2 + (iShortenedEnd + iThickness*1.5) * cos( dAngle2 ); double dY2l = iY2 + (iShortenedEnd + iThickness*1.5) * sin( dAngle2 ); DrawThickLine( dX1l,dY1l,dX2l,dY2l,uiColour,iThickness,pTarget ); } // Now draw the arrow head. // Need three points - one is end of line and others are at 60 degrees from it. DrawTriangle( dX2,dY2, dX2 + iHeadSize * cos( dAngle2 + M_PI / 6.0 ),dY2 + iHeadSize * sin( dAngle2 + M_PI / 6.0 ), dX2 + iHeadSize * cos( dAngle2 - M_PI / 6.0 ),dY2 + iHeadSize * sin( dAngle2 - M_PI / 6.0 ), uiColour,pTarget ); } /* Added in 2014 since it was used in the GroundMovement playback program so may be useful elsewhere too, but students can ignore this */ void BaseEngine::DrawShortenedLine( int iX1,int iY1,int iX2,int iY2, int iShortenedStart,int iShortenedEnd, unsigned int uiColour,int iThickness,SDL_Surface* pTarget ) { if ( pTarget == NULL ) pTarget = m_pActualScreen; double dAngle1 = GetAngle( iX1,iY1,iX2,iY2 ); double dAngle2 = dAngle1 + M_PI; // First draw the line if ( iThickness < 2 ) { // Go to the quicker draw function double dX1 = iX1 + iShortenedStart * cos( dAngle1 ); double dY1 = iY1 + iShortenedStart * sin( dAngle1 ); double dX2 = iX2 + iShortenedEnd * cos( dAngle2 ); double dY2 = iY2 + iShortenedEnd * sin( dAngle2 ); DrawLine( dX1,dY1,dX2,dY2,uiColour,pTarget ); } else { double dX1l = iX1 + iShortenedStart * cos( dAngle1 ); double dY1l = iY1 + iShortenedStart * sin( dAngle1 ); double dX2l = iX2 + iShortenedEnd * cos( dAngle2 ); double dY2l = iY2 + iShortenedEnd * sin( dAngle2 ); if ( iX1 == iX2 ) printf( "Draw shortened line %d,%d to %d,%d shortened by %d,%d is %f,%f %f,%f\n", iX1,iY1,iX2,iY2,iShortenedStart,iShortenedEnd, dX1l,dY1l,dX2l,dY2l ); DrawThickLine( dX1l,dY1l,dX2l,dY2l,uiColour,iThickness,pTarget ); } } void BaseEngine::NotifyAllObjects( int iSignalNumber ) { if (displayableObjects != NULL) { for (int i = 0; (*displayableObjects)[i] != NULL; i++) { (*displayableObjects)[i]->Notify(iSignalNumber); } } } /* Send a specified notification value to all displayable objects and count the number which give a non-zero response. */ int BaseEngine::NotifyAllObjectsGetCountNonZero( int iSignalNumber ) { int iReturn = 0; if (displayableObjects != NULL) { for (int i = 0; (*displayableObjects)[i] != NULL; i++) { if ((*displayableObjects)[i]->Notify(iSignalNumber) != 0) iReturn++; } } return iReturn; }
int main(int argc, char *argv[]) { SDL_Surface *screen, *buffer; SDL_PixelFormat *fmt; Uint32 videoflags; SDL_TimerID refreshTimerID; int width, height, bpp, refresh; int done; Uint8 *buffp; Uint32 startTimer, runTimer; int i, j; SDL_Event event; /* Initialize SDL */ if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ) { fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); exit(1); } redrawEvent.type = SDL_USEREVENT; redrawEvent.user.code = 1; redrawEvent.user.data1 = NULL; redrawEvent.user.data2 = NULL; sqsize = SQSIZE; gapsize = GAPSIZE; width = 640; height = 480; bpp = 32; back = 0; fore = 255; refresh = REFRESHRATE; frequency = FREQUENCY; videoflags = SDL_DOUBLEBUF|SDL_FULLSCREEN; while ( argc > 1 ) { --argc; if ( argv[argc-1] && (strcmp(argv[argc-1], "-w") == 0) ) { width = atoi(argv[argc]); --argc; } else if ( argv[argc-1] && (strcmp(argv[argc-1], "-h") == 0) ) { height = atoi(argv[argc]); --argc; } else if ( argv[argc-1] && (strcmp(argv[argc-1], "-gapsize") == 0) ) { gapsize = atoi(argv[argc]); --argc; } else if ( argv[argc-1] && (strcmp(argv[argc-1], "-sqsize") == 0) ) { sqsize = atoi(argv[argc]); --argc; } else if ( argv[argc-1] && (strcmp(argv[argc-1], "-freq") == 0) ) { frequency = atof(argv[argc]); --argc; } else if ( argv[argc-1] && (strcmp(argv[argc-1], "-bpp") == 0) ) { bpp = atoi(argv[argc]); --argc; } else if ( argv[argc] && (strcmp(argv[argc], "-sw") == 0) ) { videoflags |= SDL_SWSURFACE; } else if ( argv[argc] && (strcmp(argv[argc], "-i") == 0) ) { back = 255; fore = 0; } else if ( argv[argc] && (strcmp(argv[argc], "-hw") == 0) ) { videoflags |= SDL_HWSURFACE; } else if ( argv[argc] && (strcmp(argv[argc], "-hwpalette") == 0) ) { videoflags |= SDL_HWPALETTE; } else if ( argv[argc] && (strcmp(argv[argc], "-window") == 0) ) { videoflags ^= SDL_FULLSCREEN; } else { fprintf(stderr, "Usage: %s [-window] [-bpp #] [-w #] [-h #] [-gapsize #] [-sqsize #] [-i] [-freq #] [-sw] [-hw] [-hwpalette]\n", argv[0]); exit(1); } } /* Set video mode */ screen = CreateScreen(width, height, bpp, videoflags); if ( screen == NULL ) { exit(2); } /* prepare stimulus */ fmt = screen->format; bpp = screen->format->BytesPerPixel; buffer = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_HWACCEL, width, height, bpp, 0,0,0,0); buffer = SDL_DisplayFormat(buffer); SDL_LockSurface(buffer); buffp = (Uint8 *)buffer->pixels; SDL_FillRect(buffer, NULL, SDL_MapRGB(fmt, back, back, back)); for ( i=0; i<screen->h/(gapsize+sqsize); i++ ) { for ( j=0; j<screen->w/(gapsize+sqsize); j++ ) { grid.x = j*(gapsize+sqsize) + gapsize/2; grid.y = i*(gapsize+sqsize) + gapsize/2; grid.w = sqsize; grid.h = sqsize; SDL_FillRect(buffer, &grid, SDL_MapRGB(fmt, fore, fore, fore)); } } SDL_UnlockSurface(buffer); SDL_ShowCursor(SDL_DISABLE); refreshTimerID = SDL_AddTimer((int)(1000/frequency), refreshTimer, (void *)screen); runTimer = SDL_GetTicks(); done = 0; while ( !done && SDL_WaitEvent(&event) ) { switch (event.type) { case SDL_KEYDOWN: /* Ignore ALT-TAB */ if ( (event.key.keysym.sym == SDLK_LALT) || (event.key.keysym.sym == SDLK_TAB) ) { break; } /* Any key quits */ case SDL_QUIT: done = 1; break; case SDL_USEREVENT: runTimer = SDL_GetTicks(); if((int)(runTimer/(1000/frequency))%2 == 0) SDL_BlitSurface(buffer, NULL, screen, NULL); else { printf("."); /* SDL_LockSurface(screen);*/ SDL_FillRect(screen, NULL, SDL_MapRGB(fmt, back,back,back)); /*SDL_UnlockSurface(screen);*/ } SDL_Flip(screen); break; default: break; } } SDL_ShowCursor(SDL_ENABLE); SDL_Quit(); return(0); }
// Unlock func 2 static void unlockfct2(void *data, void *id, void * const *p_pixels) { SDL_UnlockSurface(sdlStruct2.sdlSurface); SDL_UnlockMutex(sdlStruct2.sdlMutex); }
void Engine::Run() { while(!endProcess_) { while(SDL_PollEvent(&event_)) { switch(event_.type) { ModuleManager::Instance()->SetType(event_.type); case SDL_ACTIVEEVENT: { if (event_.active.gain == 0) { active_ ^= true; } break; } case SDL_VIDEORESIZE: { screen_ = SDL_SetVideoMode( event_.resize.w, event_.resize.h, bits_, videoFlags_ ); Resize (event_.resize.w, event_.resize.h); width_ = event_.resize.w; height_ = event_.resize.h; break; } case SDL_MOUSEBUTTONDOWN: { ModuleManager::Instance()->SetType(SDL_MOUSEBUTTONDOWN); ModuleManager::Instance()->MouseButtonDown(event_); break; } case SDL_MOUSEMOTION: { ModuleManager::Instance()->SetType(SDL_MOUSEMOTION); ModuleManager::Instance()->MouseMotion(event_); } case SDL_KEYDOWN: { ModuleManager::Instance()->KeyDown(event_.key.keysym.sym); if(event_.key.keysym.sym == SDLK_F1) { fullscreen_ ^= true; SDL_LockSurface(screen_); ToggleFullscreen(); SDL_UnlockSurface(screen_); } else if(event_.key.keysym.sym == SDLK_F2) { showFPS_ ^= true; } else if(event_.key.keysym.sym == SDLK_F3) { ModuleManager::Instance()->ActivateNext(); } else if(event_.key.keysym.sym == SDLK_ESCAPE) { endProcess_ = true; } break; } case SDL_KEYUP: { ModuleManager::Instance()->KeyUp(event_.key.keysym.sym); break; } case SDL_QUIT: { endProcess_ = true; break; } default: { ModuleManager::Instance()->SetType(event_.type); } } } if(timer_->ReadyForNextFrame()) { Update(timer_->TimeElapsed()); } Render(); SDL_GL_SwapBuffers(); } }