texture.monkey2 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. Namespace mojo.graphics
  2. #rem monkeydoc Texture flags.
  3. | TextureFlags | Description
  4. |:--------------|:-----------
  5. | Filter | Enable filtering. When the texture is magnified, texel colors are interpolated giving a smooth/blurred result.
  6. | Mipmap | Enable mipmapping. When the texture is minified, automatically pre-generated 'mipmaps' are used to give a smoother result.
  7. | Dynamic | Texture is frequently updated. This flag should be set if the texture contents are regularly updated and don't need to be preserved.
  8. #end
  9. Enum TextureFlags
  10. Filter= $0001
  11. Mipmap= $0002
  12. WrapS= $0004 'wrap works, but hidden for now...
  13. WrapT= $0008
  14. WrapST= WrapS|WrapT
  15. Dynamic= $1000
  16. End
  17. #rem monkeydoc @hidden
  18. #end
  19. Class Texture
  20. #rem monkeydoc @hidden
  21. #end
  22. Field OnDiscarded:Void()
  23. Method New( pixmap:Pixmap,flags:TextureFlags=TextureFlags.Filter|TextureFlags.Mipmap )
  24. #If __TARGET__<>"desktop"
  25. If flags & TextureFlags.Mipmap
  26. Local tw:=Log2( pixmap.Width ),th:=Log2( pixmap.Height )
  27. If tw<>Round( tw ) Or th<>Round( th ) flags&=~TextureFlags.Mipmap
  28. Endif
  29. #Endif
  30. _rect=New Recti( 0,0,pixmap.Width,pixmap.Height )
  31. _format=pixmap.Format
  32. _flags=flags
  33. If flags & TextureFlags.Dynamic
  34. PastePixmap( pixmap,0,0 )
  35. Else
  36. _managed=pixmap
  37. Endif
  38. End
  39. Method New( width:Int,height:Int,format:PixelFormat=PixelFormat.RGBA32,flags:TextureFlags=TextureFlags.Filter|TextureFlags.Mipmap )
  40. _rect=New Recti( 0,0,width,height )
  41. _format=format
  42. _flags=flags
  43. If Not (_flags & TextureFlags.Dynamic)
  44. _managed=New Pixmap( width,height,format )
  45. _managed.Clear( Color.Magenta )
  46. OnDiscarded+=Lambda()
  47. _managed.Discard()
  48. _managed=Null
  49. End
  50. Endif
  51. End
  52. Property Rect:Recti()
  53. Return _rect
  54. End
  55. Property Width:Int()
  56. Return _rect.Width
  57. End
  58. Property Height:Int()
  59. Return _rect.Height
  60. End
  61. Property Format:PixelFormat()
  62. Return _format
  63. End
  64. Property Flags:TextureFlags()
  65. Return _flags
  66. End
  67. Method Discard()
  68. If _discarded Return
  69. If _texSeq=glGraphicsSeq glDeleteTextures( 1,Varptr _glTexture )
  70. If _fbSeq=glGraphicsSeq glDeleteFramebuffers( 1,Varptr _glFramebuffer )
  71. _discarded=True
  72. OnDiscarded()
  73. End
  74. Method PastePixmap( pixmap:Pixmap,x:Int,y:Int )
  75. If _managed
  76. _managed.Paste( pixmap,x,y )
  77. _texDirty=True
  78. Else
  79. glPushTexture2d( GLTexture )
  80. glPixelStorei( GL_UNPACK_ALIGNMENT,1 )
  81. If pixmap.Pitch=pixmap.Width*pixmap.Depth
  82. glTexSubImage2D( GL_TEXTURE_2D,0,x,y,pixmap.Width,pixmap.Height,glFormat( _format ),GL_UNSIGNED_BYTE,pixmap.Data )
  83. Else
  84. For Local iy:=0 Until pixmap.Height
  85. glTexSubImage2D( GL_TEXTURE_2D,0,x,y+iy,pixmap.Width,1,glFormat( _format ),GL_UNSIGNED_BYTE,pixmap.PixelPtr( 0,iy ) )
  86. Next
  87. Endif
  88. glPopTexture2d()
  89. _mipsDirty=True
  90. Endif
  91. End
  92. Function Load:Texture( path:String,flags:TextureFlags=TextureFlags.Filter|TextureFlags.Mipmap )
  93. Local pixmap:=Pixmap.Load( path )
  94. If Not pixmap Return Null
  95. pixmap.PremultiplyAlpha()
  96. Local texture:=New Texture( pixmap,flags )
  97. texture.OnDiscarded+=Lambda()
  98. pixmap.Discard()
  99. End
  100. Return texture
  101. End
  102. Function ColorTexture:Texture( color:Color )
  103. Local texture:=_colorTextures[color]
  104. If Not texture
  105. Local pixmap:=New Pixmap( 1,1 )
  106. pixmap.Clear( color )
  107. texture=New Texture( pixmap,Null )
  108. _colorTextures[color]=texture
  109. Endif
  110. Return texture
  111. End
  112. #rem monkeydoc @hidden
  113. #end
  114. Property GLTexture:GLuint()
  115. If _discarded Return 0
  116. ' DebugAssert( Not _discarded,"texture has been discarded" )
  117. If _texSeq=glGraphicsSeq And Not _texDirty And Not _mipsDirty Return _glTexture
  118. If _texSeq=glGraphicsSeq
  119. glPushTexture2d( _glTexture )
  120. Else
  121. glGenTextures( 1,Varptr _glTexture )
  122. glPushTexture2d( _glTexture )
  123. If _flags & TextureFlags.Filter
  124. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR )
  125. Else
  126. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST )
  127. Endif
  128. If (_flags & TextureFlags.Mipmap) And (_flags & TextureFlags.Filter)
  129. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR )
  130. Else If _flags & TextureFlags.Mipmap
  131. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST )
  132. Else If _flags & TextureFlags.Filter
  133. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR )
  134. Else
  135. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST )
  136. Endif
  137. If _flags & TextureFlags.WrapS
  138. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT )
  139. Else
  140. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE )
  141. Endif
  142. If _flags & TextureFlags.WrapT
  143. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT )
  144. Else
  145. glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE )
  146. Endif
  147. glTexImage2D( GL_TEXTURE_2D,0,glFormat( _format ),Width,Height,0,glFormat( _format ),GL_UNSIGNED_BYTE,Null )
  148. _texSeq=glGraphicsSeq
  149. _texDirty=True
  150. Endif
  151. If _texDirty
  152. If _managed
  153. glPixelStorei( GL_UNPACK_ALIGNMENT,1 )
  154. If _managed.Pitch=_managed.Width*_managed.Depth
  155. glTexSubImage2D( GL_TEXTURE_2D,0,0,0,_managed.Width,_managed.Height,glFormat( _format ),GL_UNSIGNED_BYTE,_managed.Data )
  156. Else
  157. For Local iy:=0 Until Height
  158. glTexSubImage2D( GL_TEXTURE_2D,0,0,iy,Width,1,glFormat( _format ),GL_UNSIGNED_BYTE,_managed.PixelPtr( 0,iy ) )
  159. Next
  160. Endif
  161. glFlush() 'macos nvidia bug!
  162. Else
  163. Local tmp:=New Pixmap( Width,1,Format )
  164. tmp.Clear( Color.Red )
  165. For Local iy:=0 Until Height
  166. glTexSubImage2D( GL_TEXTURE_2D,0,0,iy,Width,1,glFormat( _format ),GL_UNSIGNED_BYTE,tmp.Data )
  167. Next
  168. tmp.Discard()
  169. Endif
  170. _texDirty=False
  171. _mipsDirty=True
  172. Endif
  173. If _mipsDirty
  174. If _flags & TextureFlags.Mipmap glGenerateMipmap( GL_TEXTURE_2D )
  175. _mipsDirty=False
  176. End
  177. glPopTexture2d()
  178. Return _glTexture
  179. End
  180. #rem monkeydoc @hidden
  181. #end
  182. Property GLFramebuffer:GLuint()
  183. DebugAssert( Not _discarded,"texture has been discarded" )
  184. If _fbSeq=glGraphicsSeq Return _glFramebuffer
  185. glGenFramebuffers( 1,Varptr _glFramebuffer )
  186. glPushFramebuffer( _glFramebuffer )
  187. glBindFramebuffer( GL_FRAMEBUFFER,_glFramebuffer )
  188. glFramebufferTexture2D( GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,GLTexture,0 )
  189. If glCheckFramebufferStatus( GL_FRAMEBUFFER )<>GL_FRAMEBUFFER_COMPLETE Assert( False,"Incomplete framebuffer" )
  190. glPopFramebuffer()
  191. _fbSeq=glGraphicsSeq
  192. Return _glFramebuffer
  193. End
  194. '***** INTERNAL *****
  195. #rem monkeydoc @hidden
  196. #end
  197. Method Modified( device:GraphicsDevice )
  198. If _managed
  199. Local r:=device.Viewport & device.Scissor
  200. glPixelStorei( GL_PACK_ALIGNMENT,1 )
  201. glReadPixels( r.X,r.Y,r.Width,r.Height,GL_RGBA,GL_UNSIGNED_BYTE,_managed.PixelPtr( r.X,r.Y ) )
  202. Endif
  203. If _flags & TextureFlags.Mipmap _mipsDirty=True
  204. End
  205. Private
  206. Field _rect:Recti
  207. Field _format:PixelFormat
  208. Field _flags:TextureFlags
  209. Field _managed:Pixmap
  210. Field _discarded:Bool
  211. Field _texSeq:Int
  212. Field _texDirty:Bool
  213. Field _mipsDirty:Bool
  214. Field _glTexture:GLuint
  215. Field _fbSeq:Int
  216. Field _glFramebuffer:GLuint
  217. Global _colorTextures:Map<Color,Texture>
  218. End