src/video/SDL_video.c
branchSDL-1.3
changeset 1654 0a53c90a37f9
parent 1545 8d9bb0cf2c2a
child 1655 59227394023d
equal deleted inserted replaced
1653:939d938d62df 1654:0a53c90a37f9
   129 SDL_VideoDevice *current_video = NULL;
   129 SDL_VideoDevice *current_video = NULL;
   130 
   130 
   131 /* Various local functions */
   131 /* Various local functions */
   132 int SDL_VideoInit(const char *driver_name, Uint32 flags);
   132 int SDL_VideoInit(const char *driver_name, Uint32 flags);
   133 void SDL_VideoQuit(void);
   133 void SDL_VideoQuit(void);
   134 void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect* rects);
       
   135 
   134 
   136 static SDL_GrabMode SDL_WM_GrabInputOff(void);
   135 static SDL_GrabMode SDL_WM_GrabInputOff(void);
   137 #if SDL_VIDEO_OPENGL
       
   138 static int lock_count = 0;
       
   139 #endif
       
   140 
   136 
   141 
   137 
   142 /*
   138 /*
   143  * Initialize the video and event subsystems -- determine native pixel format
   139  * Initialize the video and event subsystems -- determine native pixel format
   144  */
   140  */
   575 	int video_h;
   571 	int video_h;
   576 	int video_bpp;
   572 	int video_bpp;
   577 	int is_opengl;
   573 	int is_opengl;
   578 	SDL_GrabMode saved_grab;
   574 	SDL_GrabMode saved_grab;
   579 
   575 
       
   576 	/* Handle obsolete flags */
       
   577 	if ( (flags & SDL_OPENGLBLIT_OBSOLETE) == SDL_OPENGLBLIT_OBSOLETE ) {
       
   578 		SDL_SetError("SDL_OPENGLBLIT is no longer supported");
       
   579 		return(NULL);
       
   580 	}
       
   581 
   580 	/* Start up the video driver, if necessary..
   582 	/* Start up the video driver, if necessary..
   581 	   WARNING: This is the only function protected this way!
   583 	   WARNING: This is the only function protected this way!
   582 	 */
   584 	 */
   583 	if ( ! current_video ) {
   585 	if ( ! current_video ) {
   584 		if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
   586 		if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
   746 	SDL_WM_GrabInput(saved_grab);
   748 	SDL_WM_GrabInput(saved_grab);
   747 	SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
   749 	SDL_GetRelativeMouseState(NULL, NULL); /* Clear first large delta */
   748 
   750 
   749 #if SDL_VIDEO_OPENGL
   751 #if SDL_VIDEO_OPENGL
   750 	/* Load GL symbols (before MakeCurrent, where we need glGetString). */
   752 	/* Load GL symbols (before MakeCurrent, where we need glGetString). */
   751 	if ( flags & (SDL_OPENGL | SDL_OPENGLBLIT) ) {
   753 	if ( flags & SDL_OPENGL ) {
   752 
   754 
   753 #if defined(__QNXNTO__) && (_NTO_VERSION < 630)
   755 #if defined(__QNXNTO__) && (_NTO_VERSION < 630)
   754 #define __SDL_NOGETPROCADDR__
   756 #define __SDL_NOGETPROCADDR__
   755 #elif defined(__MINT__)
   757 #elif defined(__MINT__)
   756 #define __SDL_NOGETPROCADDR__
   758 #define __SDL_NOGETPROCADDR__
   778 	if ( (video->screen->flags & SDL_OPENGL) &&
   780 	if ( (video->screen->flags & SDL_OPENGL) &&
   779 	      video->GL_MakeCurrent ) {
   781 	      video->GL_MakeCurrent ) {
   780 		if ( video->GL_MakeCurrent(this) < 0 ) {
   782 		if ( video->GL_MakeCurrent(this) < 0 ) {
   781 			return(NULL);
   783 			return(NULL);
   782 		}
   784 		}
   783 	}
       
   784 
       
   785 	/* Set up a fake SDL surface for OpenGL "blitting" */
       
   786 	if ( (flags & SDL_OPENGLBLIT) == SDL_OPENGLBLIT ) {
       
   787 		/* Load GL functions for performing the texture updates */
       
   788 #if SDL_VIDEO_OPENGL
       
   789 
       
   790 		/* Create a software surface for blitting */
       
   791 #ifdef GL_VERSION_1_2
       
   792 		/* If the implementation either supports the packed pixels
       
   793 		   extension, or implements the core OpenGL 1.2 API, it will
       
   794 		   support the GL_UNSIGNED_SHORT_5_6_5 texture format.
       
   795 		 */
       
   796 		if ( (bpp == 16) &&
       
   797 		     (SDL_strstr((const char *)video->glGetString(GL_EXTENSIONS), "GL_EXT_packed_pixels") ||
       
   798 		     (SDL_atof((const char *)video->glGetString(GL_VERSION)) >= 1.2f))
       
   799 		   ) {
       
   800 			video->is_32bit = 0;
       
   801 			SDL_VideoSurface = SDL_CreateRGBSurface(
       
   802 				flags, 
       
   803 				width, 
       
   804 				height,  
       
   805 				16,
       
   806 				31 << 11,
       
   807 				63 << 5,
       
   808 				31,
       
   809 				0
       
   810 				);
       
   811 		}
       
   812 		else
       
   813 #endif /* OpenGL 1.2 */
       
   814 		{
       
   815 			video->is_32bit = 1;
       
   816 			SDL_VideoSurface = SDL_CreateRGBSurface(
       
   817 				flags, 
       
   818 				width, 
       
   819 				height, 
       
   820 				32, 
       
   821 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
       
   822 				0x000000FF,
       
   823 				0x0000FF00,
       
   824 				0x00FF0000,
       
   825 				0xFF000000
       
   826 #else
       
   827 				0xFF000000,
       
   828 				0x00FF0000,
       
   829 				0x0000FF00,
       
   830 				0x000000FF
       
   831 #endif
       
   832 				);
       
   833 		}
       
   834 		if ( ! SDL_VideoSurface ) {
       
   835 			return(NULL);
       
   836 		}
       
   837 		SDL_VideoSurface->flags = mode->flags | SDL_OPENGLBLIT;
       
   838 
       
   839 		/* Free the original video mode surface (is this safe?) */
       
   840 		SDL_FreeSurface(mode);
       
   841 
       
   842 		/* Set the surface completely opaque & white by default */
       
   843 		SDL_memset( SDL_VideoSurface->pixels, 255, SDL_VideoSurface->h * SDL_VideoSurface->pitch );
       
   844 		video->glGenTextures( 1, &video->texture );
       
   845 		video->glBindTexture( GL_TEXTURE_2D, video->texture );
       
   846 		video->glTexImage2D(
       
   847 			GL_TEXTURE_2D,
       
   848 			0,
       
   849 			video->is_32bit ? GL_RGBA : GL_RGB,
       
   850 			256,
       
   851 			256,
       
   852 			0,
       
   853 			video->is_32bit ? GL_RGBA : GL_RGB,
       
   854 #ifdef GL_VERSION_1_2
       
   855 			video->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
       
   856 #else
       
   857 			GL_UNSIGNED_BYTE,
       
   858 #endif
       
   859 			NULL);
       
   860 
       
   861 		video->UpdateRects = SDL_GL_UpdateRectsLock;
       
   862 #else
       
   863 		SDL_SetError("Somebody forgot to #define SDL_VIDEO_OPENGL");
       
   864 		return(NULL);
       
   865 #endif
       
   866 	}
   785 	}
   867 
   786 
   868 	/* Create a shadow surface if necessary */
   787 	/* Create a shadow surface if necessary */
   869 	/* There are three conditions under which we create a shadow surface:
   788 	/* There are three conditions under which we create a shadow surface:
   870 		1.  We need a particular bits-per-pixel that we didn't get.
   789 		1.  We need a particular bits-per-pixel that we didn't get.
  1509 	} else {
  1428 	} else {
  1510 		SDL_SetError("OpenGL video mode has not been set");
  1429 		SDL_SetError("OpenGL video mode has not been set");
  1511 	}
  1430 	}
  1512 }
  1431 }
  1513 
  1432 
  1514 /* Update rects with locking */
       
  1515 void SDL_GL_UpdateRectsLock(SDL_VideoDevice* this, int numrects, SDL_Rect *rects)
       
  1516 {
       
  1517 	SDL_GL_Lock();
       
  1518  	SDL_GL_UpdateRects(numrects, rects);
       
  1519 	SDL_GL_Unlock();
       
  1520 }
       
  1521 
       
  1522 /* Update rects without state setting and changing (the caller is responsible for it) */
       
  1523 void SDL_GL_UpdateRects(int numrects, SDL_Rect *rects)
       
  1524 {
       
  1525 #if SDL_VIDEO_OPENGL
       
  1526 	SDL_VideoDevice *this = current_video;
       
  1527 	SDL_Rect update, tmp;
       
  1528 	int x, y, i;
       
  1529 
       
  1530 	for ( i = 0; i < numrects; i++ )
       
  1531 	{
       
  1532 		tmp.y = rects[i].y;
       
  1533 		tmp.h = rects[i].h;
       
  1534 		for ( y = 0; y <= rects[i].h / 256; y++ )
       
  1535 		{
       
  1536 			tmp.x = rects[i].x;
       
  1537 			tmp.w = rects[i].w;
       
  1538 			for ( x = 0; x <= rects[i].w / 256; x++ )
       
  1539 			{
       
  1540 				update.x = tmp.x;
       
  1541 				update.y = tmp.y;
       
  1542 				update.w = tmp.w;
       
  1543 				update.h = tmp.h;
       
  1544 
       
  1545 				if ( update.w > 256 )
       
  1546 					update.w = 256;
       
  1547 
       
  1548 				if ( update.h > 256 )
       
  1549 					update.h = 256;
       
  1550 			
       
  1551 				this->glFlush();
       
  1552 				this->glTexSubImage2D( 
       
  1553 					GL_TEXTURE_2D, 
       
  1554 					0, 
       
  1555 					0, 
       
  1556 					0, 
       
  1557 					update.w, 
       
  1558 					update.h, 
       
  1559 					this->is_32bit? GL_RGBA : GL_RGB,
       
  1560 #ifdef GL_VERSION_1_2
       
  1561 					this->is_32bit ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
       
  1562 #else
       
  1563 					GL_UNSIGNED_BYTE,
       
  1564 #endif
       
  1565 					(Uint8 *)this->screen->pixels + 
       
  1566 						this->screen->format->BytesPerPixel * update.x + 
       
  1567 						update.y * this->screen->pitch );
       
  1568 	
       
  1569 				this->glFlush();
       
  1570 				/*
       
  1571 				* Note the parens around the function name:
       
  1572 				* This is because some OpenGL implementations define glTexCoord etc 
       
  1573 				* as macros, and we don't want them expanded here.
       
  1574 				*/
       
  1575 				this->glBegin(GL_TRIANGLE_STRIP);
       
  1576 					(this->glTexCoord2f)( 0.0, 0.0 );	
       
  1577 					(this->glVertex2i)( update.x, update.y );
       
  1578 					(this->glTexCoord2f)( (float)(update.w / 256.0), 0.0 );	
       
  1579 					(this->glVertex2i)( update.x + update.w, update.y );
       
  1580 					(this->glTexCoord2f)( 0.0, (float)(update.h / 256.0) );
       
  1581 					(this->glVertex2i)( update.x, update.y + update.h );
       
  1582 					(this->glTexCoord2f)( (float)(update.w / 256.0), (float)(update.h / 256.0) );	
       
  1583 					(this->glVertex2i)( update.x + update.w	, update.y + update.h );
       
  1584 				this->glEnd();	
       
  1585 			
       
  1586 				tmp.x += 256;
       
  1587 				tmp.w -= 256;
       
  1588 			}
       
  1589 			tmp.y += 256;
       
  1590 			tmp.h -= 256;
       
  1591 		}
       
  1592 	}
       
  1593 #endif
       
  1594 }
       
  1595 
       
  1596 /* Lock == save current state */
       
  1597 void SDL_GL_Lock()
       
  1598 {
       
  1599 #if SDL_VIDEO_OPENGL
       
  1600 	lock_count--;
       
  1601 	if (lock_count==-1)
       
  1602 	{
       
  1603 		SDL_VideoDevice *this = current_video;
       
  1604 
       
  1605 		this->glPushAttrib( GL_ALL_ATTRIB_BITS );	/* TODO: narrow range of what is saved */
       
  1606 #ifdef GL_CLIENT_PIXEL_STORE_BIT
       
  1607 		this->glPushClientAttrib( GL_CLIENT_PIXEL_STORE_BIT );
       
  1608 #endif
       
  1609 
       
  1610 		this->glEnable(GL_TEXTURE_2D);
       
  1611 		this->glEnable(GL_BLEND);
       
  1612 		this->glDisable(GL_FOG);
       
  1613 		this->glDisable(GL_ALPHA_TEST);
       
  1614 		this->glDisable(GL_DEPTH_TEST);
       
  1615 		this->glDisable(GL_SCISSOR_TEST);	
       
  1616 		this->glDisable(GL_STENCIL_TEST);
       
  1617 		this->glDisable(GL_CULL_FACE);
       
  1618 
       
  1619 		this->glBindTexture( GL_TEXTURE_2D, this->texture );
       
  1620 		this->glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
       
  1621 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
       
  1622 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
       
  1623 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
       
  1624 		this->glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
       
  1625 
       
  1626 		this->glPixelStorei( GL_UNPACK_ROW_LENGTH, this->screen->pitch / this->screen->format->BytesPerPixel );
       
  1627 		this->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       
  1628 		(this->glColor4f)(1.0, 1.0, 1.0, 1.0);		/* Solaris workaround */
       
  1629 
       
  1630 		this->glViewport(0, 0, this->screen->w, this->screen->h);
       
  1631 		this->glMatrixMode(GL_PROJECTION);
       
  1632 		this->glPushMatrix();
       
  1633 		this->glLoadIdentity();
       
  1634 
       
  1635 		this->glOrtho(0.0, (GLdouble) this->screen->w, (GLdouble) this->screen->h, 0.0, 0.0, 1.0);
       
  1636 
       
  1637 		this->glMatrixMode(GL_MODELVIEW);
       
  1638 		this->glPushMatrix();
       
  1639 		this->glLoadIdentity();
       
  1640 	}
       
  1641 #endif
       
  1642 }
       
  1643 
       
  1644 /* Unlock == restore saved state */
       
  1645 void SDL_GL_Unlock()
       
  1646 {
       
  1647 #if SDL_VIDEO_OPENGL
       
  1648 	lock_count++;
       
  1649 	if (lock_count==0)
       
  1650 	{
       
  1651 		SDL_VideoDevice *this = current_video;
       
  1652 
       
  1653 		this->glPopMatrix();
       
  1654 		this->glMatrixMode(GL_PROJECTION);
       
  1655 		this->glPopMatrix();
       
  1656 
       
  1657 		this->glPopClientAttrib();
       
  1658 		this->glPopAttrib();
       
  1659 	}
       
  1660 #endif
       
  1661 }
       
  1662 
       
  1663 /*
  1433 /*
  1664  * Sets/Gets the title and icon text of the display window, if any.
  1434  * Sets/Gets the title and icon text of the display window, if any.
  1665  */
  1435  */
  1666 void SDL_WM_SetCaption (const char *title, const char *icon)
  1436 void SDL_WM_SetCaption (const char *title, const char *icon)
  1667 {
  1437 {