DX Render to Texture

BlitzMax Forums/BlitzMax Programming/DX Render to Texture

This is a bit hacky and, I'm sure, could be cleaned up.
I have tried to comment but, in some cases, I had no idea what I was doing.
Feedback and comments appreciated.
Strict
Graphics 640,480
Local image1:TImage=LoadImage("max.png") 
Local image2:TImage=LoadImage("light.png")
' Because Bmax users DX Texture Manager it is necessary to create a dummy rendertarget surface
' and then blit from that surface to the image surface.
Global mysurf:IDirectDrawSurface7   ' The dummy surf to be used as the rendertarget.
While Not KeyHit(KEY_ESCAPE)
   render2image_start(image1)   ' set image1 as the destination image for the draw
   SetBlend lightblend
   DrawImage image2,0,0 
   SetColor 255,0,0 
   SetBlend alphablend
   SetAlpha 0.5
   DrawOval 0,0,200,200
   SetColor 255,255,255
   render2image_stop(image1)    ' stop rendering to the image and reset to the backbuffer
   Cls
   SetBlend maskblend
   SetAlpha 1.0
   DrawImage image1,0,0         ' draw the new image
   DrawText GCMemAlloced(),0,300
   Flip
Wend
Function render2image_start(image:TImage,frame:Int=0)
	Local mypix:TPixmap=LockImage(image)  ' lock the image to obtain a pixmap.
    mysurf:IDirectDrawSurface7=createsurffrompixmap(mypix)  ' Create the rendertarget surface
	Local res=PrimaryDevice.Device.SetRenderTarget(mysurf,0)  ' set the new surface as the rendertarget.
	If res<>DD_OK RuntimeError "D3D7Max2D Rendertarget failed" ' Check it worked OK.
	Cls  ' Clear the rendertarget
	DrawImage image,0,0  'need to copy the 'destination' image to the render surface.
End Function
Function render2image_stop(image:TImage,frame=0)
    ' Set the src and dest sizes to copy from/to. Thought I could leave these null but it produces horrid results.
    ' These parms could be used to copy a part of an image to another.
	Local src[]=[0,0,ImageWidth(image),ImageHeight(image)]  	
	Local dest[]=[0,0,ImageWidth(image),ImageHeight(image)]  
	dest[2]:+dest[0]
	dest[3]:+dest[1]
	' Do the blit from the dummy rendertarget to the image surface.
	TD3D7ImageFrame(image.frame(frame)).surface.Blt dest,mysurf,src,0,Null
	' Release the surface
	mysurf.release_()
	' reset rendering to the backbuffer
    render2backbuffer()
End Function
Function render2backbuffer()
    'set the rendertarget to the backbuffer
   	PrimaryDevice.Device.SetRenderTarget PrimaryDevice.backbuffer,0
End Function
Function createsurffrompixmap:IDirectDrawSurface7(temppix:TPixmap)
'lifted and butchered from Bmax source.
' I Don't use the POW2SIZE in this case.
		Function Pow2Size( n )
			Local t=1
			While t<n
				t:*2
			Wend
			Return t
		End Function
		Local 	surf:IDirectDrawSurface7  ' The dummy surface to return as the rendertarget
		Local	desc:DDSURFACEDESC2=New DDSURFACEDESC2  ' the 'description' of the surface
		Local	res   ' Used to hold the return code of DX operations.
		desc.dwSize=SizeOf(desc)  ' size of the description 
		desc.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_PITCH   'Something to do with valid members?
		desc.dwWidth=temppix.width   ' Width of the surface = to the pixmap width
		desc.dwHeight=temppix.height ' Same but for height.
		desc.lPitch=temppix.pitch  ' Think this is for pixmap memory location
		desc.lpSurface=temppix.pixels ' and this
		desc.ddsCaps=DDSCAPS_3DDEVICE|DDSCAPS_VIDEOMEMORY  ' Surface can be rendered to and held in videomem.
		desc.ddpf_dwSize=SizeOf(DDPIXELFORMAT)
		Select temppix.format
			Case PF_BGR888
				desc.ddpf_dwFlags=DDPF_RGB
				desc.ddpf_BitCount=24
				desc.ddpf_BitMask_0=$ff0000
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$0000ff
			Case PF_RGB888
				desc.ddpf_dwFlags=DDPF_RGB
				desc.ddpf_BitCount=24
				desc.ddpf_BitMask_0=$0000ff
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$ff0000
			Case PF_BGRA8888
				desc.ddpf_dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS
				desc.ddpf_BitCount=32
				desc.ddpf_BitMask_0=$ff0000
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$0000ff
				desc.ddpf_BitMask_3=$ff000000
			Case PF_RGBA8888
				desc.ddpf_dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS
				desc.ddpf_BitCount=32
				desc.ddpf_BitMask_0=$0000ff
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$ff0000
				desc.ddpf_BitMask_3=$ff000000
		End Select	
		' Create the surface and return the result into RES	
		res=PrimaryDevice.DDraw.CreateSurface( desc,Varptr surf,Null )
		If res<>DD_OK RuntimeError "D3D7Max2D Create System Surface Failed"
		Return surf		
End Function

P.S. Not a huge amount of testing done on this either.
<edit> Hmmm, oddly it remembers images drawn to it between renders but not primitives when they're drawn in the mainloop. Anybody see what's wrong?
<edit> Actually, it just doesn't remember what was rendered. It must be an error in my blt.