texture.c 33.5 KB
Newer Older
1
/* Direct3D Texture
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 * Copyright (c) 1998 Lionel ULMER
 *
 * This file contains the implementation of interface Direct3DTexture2.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
20 21

#include "config.h"
22
#include "wine/port.h"
23

24
#include <stdarg.h>
25 26
#include <string.h>

27 28
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
29

30
#include "windef.h"
31
#include "winbase.h"
32
#include "winerror.h"
33
#include "objbase.h"
34
#include "wingdi.h"
35 36
#include "ddraw.h"
#include "d3d.h"
37
#include "wine/debug.h"
38

39
#include "opengl_private.h"
40

41
WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
42
WINE_DECLARE_DEBUG_CHANNEL(ddraw_tex);
43

44
#include <stdio.h>
45

46 47
static void 
snoop_texture(IDirectDrawSurfaceImpl *This) {
48 49 50
    IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
    char buf[128];
    FILE *f;
51 52 53

    TRACE_(ddraw_tex)("Dumping surface id (%5d) level (%2d) : \n", glThis->tex_name, This->mipmap_level);
    DDRAW_dump_surface_desc(&(This->surface_desc));
54
    
55
    sprintf(buf, "tex_%05d_%02d.pnm", glThis->tex_name, This->mipmap_level);
56
    f = fopen(buf, "wb");
57
    DDRAW_dump_surface_to_disk(This, f, 1);
58
}
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
static IDirectDrawSurfaceImpl *
get_sub_mimaplevel(IDirectDrawSurfaceImpl *tex_ptr)
{
    /* Now go down the mipmap chain to the next surface */
    static const DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
    LPDIRECTDRAWSURFACE7 next_level;
    IDirectDrawSurfaceImpl *surf_ptr;
    HRESULT hr;
    
    hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(tex_ptr, IDirectDrawSurface7),
						(DDSCAPS2 *) &mipmap_caps, &next_level);
    if (FAILED(hr)) return NULL;
    
    surf_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, next_level);
    IDirectDrawSurface7_Release(next_level);
    
    return surf_ptr;
}

79
/*******************************************************************************
80
 *			   IDirectSurface callback methods
81
 */
82

83
HRESULT
84
gltex_download_texture(IDirectDrawSurfaceImpl *surf_ptr) {
85 86 87 88
    IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;

    FIXME("This is not supported yet... Expect some graphical glitches !!!\n");

89 90 91
    /* GL and memory are in sync again ... 
       No need to change the 'global' flag as it only handles the 'MEMORY_DIRTY' case.
    */
92 93 94 95 96
    gl_surf_ptr->dirty_flag = SURFACE_MEMORY;
    
    return DD_OK;
}

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
static GLenum
convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
{
    GLenum gl_state;

    if (dwMipState == D3DTFP_NONE) {
        switch (dwMinState) {
            case D3DTFN_POINT:  gl_state = GL_NEAREST; break;
	    case D3DTFN_LINEAR: gl_state = GL_LINEAR;  break;
	    default:            gl_state = GL_LINEAR;  break;
	}
    } else if (dwMipState == D3DTFP_POINT) {
        switch (dwMinState) {
            case D3DTFN_POINT:  gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
	    case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST;  break;
	    default:            gl_state = GL_LINEAR_MIPMAP_NEAREST;  break;
	}
    } else {
        switch (dwMinState) {
            case D3DTFN_POINT:  gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
	    case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR;  break;
	    default:            gl_state = GL_LINEAR_MIPMAP_LINEAR;  break;
	}
    }
    return gl_state;
}

static GLenum
convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
{
    GLenum gl_state;

    switch (dwState) {
        case D3DTFG_POINT:
	    gl_state = GL_NEAREST;
	    break;
        case D3DTFG_LINEAR:
	    gl_state = GL_LINEAR;
	    break;
        default:
	    gl_state = GL_LINEAR;
	    break;
    }
    return gl_state;
}

static GLenum
convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
{
    GLenum gl_state;
    switch (dwState) {
        case D3DTADDRESS_WRAP:   gl_state = GL_REPEAT; break;
	case D3DTADDRESS_CLAMP:  gl_state = GL_CLAMP; break;
	case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
151
	case D3DTADDRESS_MIRROR:
152
	    if (GL_extensions.mirrored_repeat) {
153 154 155 156 157 158 159 160 161
		gl_state = GL_MIRRORED_REPEAT_WINE;
	    } else {
		gl_state = GL_REPEAT;
		/* This is a TRACE instead of a FIXME as the FIXME was already printed when the game
		   actually set D3DTADDRESS_MIRROR.
		*/
		TRACE(" setting GL_REPEAT instead of GL_MIRRORED_REPEAT.\n");
	    }
	break;
162 163 164 165 166
	default:                 gl_state = GL_REPEAT; break;
    }
    return gl_state;
}

167
HRESULT
168
gltex_upload_texture(IDirectDrawSurfaceImpl *surf_ptr, IDirect3DDeviceImpl *d3ddev, DWORD stage) {
169
    IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
170
    IDirect3DDeviceGLImpl *gl_d3ddev = (IDirect3DDeviceGLImpl *) d3ddev;
171
    BOOLEAN changed = FALSE;
172
    GLenum unit = GL_TEXTURE0_WINE + stage;
173
    
174 175
    if (surf_ptr->mipmap_level != 0) {
        WARN(" application activating a sub-level of the mipmapping chain (level %d) !\n", surf_ptr->mipmap_level);
176
    }
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

    /* Now check if the texture parameters for this texture are still in-line with what D3D expect
       us to do..

       NOTE: there is no check for the situation where the same texture is bound to multiple stage
             but with different parameters per stage.
    */
    if ((gl_surf_ptr->tex_parameters == NULL) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_MAXMIPLEVEL - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1])) {
	DWORD max_mip_level;
	
	if ((surf_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
	    max_mip_level = 0;
	} else {
	    max_mip_level = surf_ptr->surface_desc.u2.dwMipMapCount - 1;
	    if (d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1] != 0) {
		if (max_mip_level >= d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1]) {
		    max_mip_level = d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1] - 1;
		}
	    }
	}
199 200 201 202
	if (unit != gl_d3ddev->current_active_tex_unit) {
	    GL_extensions.glActiveTexture(unit);
	    gl_d3ddev->current_active_tex_unit = unit;
	}
203 204 205 206 207 208 209
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
	changed = TRUE;
    }
    
    if ((gl_surf_ptr->tex_parameters == NULL) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_MAGFILTER - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAGFILTER - 1])) {
210 211 212 213
	if (unit != gl_d3ddev->current_active_tex_unit) {
	    GL_extensions.glActiveTexture(unit);
	    gl_d3ddev->current_active_tex_unit = unit;
	}
214 215 216 217 218 219 220 221 222
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
			convert_mag_filter_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAGFILTER - 1]));
	changed = TRUE;
    }
    if ((gl_surf_ptr->tex_parameters == NULL) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_MINFILTER - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_MINFILTER - 1]) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_MIPFILTER - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_MIPFILTER - 1])) {
223 224 225 226
	if (unit != gl_d3ddev->current_active_tex_unit) {
	    GL_extensions.glActiveTexture(unit);
	    gl_d3ddev->current_active_tex_unit = unit;
	}
227 228 229 230 231 232 233 234
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
			convert_min_filter_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_MINFILTER - 1],
						 d3ddev->state_block.texture_stage_state[stage][D3DTSS_MIPFILTER - 1]));
	changed = TRUE;
    }
    if ((gl_surf_ptr->tex_parameters == NULL) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_ADDRESSU - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1])) {
235 236 237 238
	if (unit != gl_d3ddev->current_active_tex_unit) {
	    GL_extensions.glActiveTexture(unit);
	    gl_d3ddev->current_active_tex_unit = unit;
	}
239 240 241 242 243 244 245
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
			convert_tex_address_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1]));
	changed = TRUE;
    }
    if ((gl_surf_ptr->tex_parameters == NULL) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_ADDRESSV - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSV - 1])) {
246 247 248 249
	if (unit != gl_d3ddev->current_active_tex_unit) {
	    GL_extensions.glActiveTexture(unit);
	    gl_d3ddev->current_active_tex_unit = unit;
	}
250 251 252 253 254 255 256 257 258 259 260 261 262
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
			convert_tex_address_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSV - 1]));	
	changed = TRUE;
    }
    if ((gl_surf_ptr->tex_parameters == NULL) ||
	(gl_surf_ptr->tex_parameters[D3DTSS_BORDERCOLOR - D3DTSS_ADDRESSU] != 
	 d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1])) {
	GLfloat color[4];
	
	color[0] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
	color[1] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >>  8) & 0xFF) / 255.0;
	color[2] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >>  0) & 0xFF) / 255.0;
	color[3] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
263 264 265 266
	if (unit != gl_d3ddev->current_active_tex_unit) {
	    GL_extensions.glActiveTexture(unit);
	    gl_d3ddev->current_active_tex_unit = unit;
	}
267 268 269 270
	glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
	changed = TRUE;
    }

271
    if (changed) {
272 273 274 275 276 277 278 279 280 281 282 283
	if (gl_surf_ptr->tex_parameters == NULL) {
	    gl_surf_ptr->tex_parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
						    sizeof(DWORD) * (D3DTSS_MAXMIPLEVEL + 1 - D3DTSS_ADDRESSU));
	}
	memcpy(gl_surf_ptr->tex_parameters, &(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1]),
	       sizeof(DWORD) * (D3DTSS_MAXMIPLEVEL + 1 - D3DTSS_ADDRESSU));
    }

    if (*(gl_surf_ptr->global_dirty_flag) != SURFACE_MEMORY_DIRTY) {
	TRACE(" nothing to do - memory copy and GL state in synch for all texture levels.\n");
	return DD_OK;
    }
284 285
    
    while (surf_ptr != NULL) {
286 287 288 289 290 291 292
        IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
	
	if (gl_surf_ptr->dirty_flag != SURFACE_MEMORY_DIRTY) {
            TRACE("   - level %d already uploaded.\n", surf_ptr->mipmap_level);
	} else {
	    TRACE("   - uploading texture level %d (initial done = %d).\n",
		  surf_ptr->mipmap_level, gl_surf_ptr->initial_upload_done);
293

294
	    /* Texture snooping for the curious :-) */
295 296 297
	    if (TRACE_ON(ddraw_tex)) {
		snoop_texture(surf_ptr);
	    }
298

299 300 301 302 303
	    if (unit != gl_d3ddev->current_active_tex_unit) {
		GL_extensions.glActiveTexture(unit);
		gl_d3ddev->current_active_tex_unit = unit;
	    }
	    
304
	    if (upload_surface_to_tex_memory_init(surf_ptr, surf_ptr->mipmap_level, &(gl_surf_ptr->current_internal_format),
305
						  gl_surf_ptr->initial_upload_done == FALSE, TRUE, 0, 0) == DD_OK) {
306
	        upload_surface_to_tex_memory(NULL, 0, 0, &(gl_surf_ptr->surface_ptr));
307 308
		upload_surface_to_tex_memory_release();
		gl_surf_ptr->dirty_flag = SURFACE_MEMORY;
309
		gl_surf_ptr->initial_upload_done = TRUE;
310 311 312
	    } else {
		ERR("Problem for upload of texture %d (level = %d / initial done = %d).\n",
		    gl_surf_ptr->tex_name, surf_ptr->mipmap_level, gl_surf_ptr->initial_upload_done);
313 314
	    }
	}
315
	
316 317 318 319 320
	if (surf_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
	    surf_ptr = get_sub_mimaplevel(surf_ptr);
	} else {
	    surf_ptr = NULL;
	}
321
    }
322 323 324
    
    *(gl_surf_ptr->global_dirty_flag) = SURFACE_MEMORY;
    
325
    return DD_OK;
326
}
327

328 329 330 331
HRESULT WINAPI
Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
                                       LPDIRECT3DDEVICE lpDirect3DDevice,
                                       LPDIRECTDRAWSURFACE lpDDSurface)
332
{
333
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
334 335
    FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
    return DD_OK;
336 337
}

338 339 340 341 342
static HRESULT
gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY ckey )
{
    IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;

343
    if (glThis->dirty_flag == SURFACE_GL) {
Mike McCormack's avatar
Mike McCormack committed
344
	GLint cur_tex;
345 346

	TRACE(" flushing GL texture back to memory.\n");
347 348 349 350
	
	ENTER_GL();
	glGetIntegerv(GL_TEXTURE_BINDING_2D, &cur_tex);
	glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
351
	gltex_download_texture(This);
352 353 354 355 356
	glBindTexture(GL_TEXTURE_2D, cur_tex);
	LEAVE_GL();
    }

    glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
357
    *(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
358 359
    /* TODO: check color-keying on mipmapped surfaces... */
    
360 361 362
    return DD_OK;
}

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
HRESULT
gltex_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
	  LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
	  DWORD dwFlags, LPDDBLTFX lpbltfx)
{
    if (src != NULL) {
	IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
	if (src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) {
	    FIXME("Blt from framebuffer to texture - unsupported now, please report !\n");
	}
    }
    return DDERR_INVALIDPARAMS;
}

HRESULT
gltex_bltfast(IDirectDrawSurfaceImpl *surf_ptr, DWORD dstx,
	      DWORD dsty, LPDIRECTDRAWSURFACE7 src,
	      LPRECT rsrc, DWORD trans)
{
    if (src != NULL) {
	IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
	
	if ((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
	    ((trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) == 0)) {
	    /* This is a blt without color keying... We can use the direct copy. */
	    RECT rsrc2;
	    DWORD width, height;
Mike McCormack's avatar
Mike McCormack committed
390
	    GLint cur_tex;
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
	    IDirect3DTextureGLImpl *gl_surf_ptr = surf_ptr->tex_private;
	    int y;
	    
	    if (rsrc == NULL) {
		WARN("rsrc is NULL\n");
		rsrc = &rsrc2;
		
		rsrc->left = 0;
		rsrc->top = 0;
		rsrc->right = src_ptr->surface_desc.dwWidth;
		rsrc->bottom = src_ptr->surface_desc.dwHeight;
	    }
	    
	    width = rsrc->right - rsrc->left;
	    height = rsrc->bottom - rsrc->top;
	    
	    if (((dstx + width)  > surf_ptr->surface_desc.dwWidth) ||
		((dsty + height) > surf_ptr->surface_desc.dwHeight)) {
		FIXME("Does not handle clipping yet in FB => Texture blits !\n");
		return DDERR_INVALIDPARAMS;
	    }

413 414 415 416
	    if ((width == 0) || (height == 0)) {
		return DD_OK;
	    }
	    
417 418 419 420 421
	    TRACE(" direct frame buffer => texture BltFast override.\n");
	    
	    ENTER_GL();
	    
	    glGetIntegerv(GL_TEXTURE_BINDING_2D, &cur_tex);
422 423
	    /* This call is to create the actual texture name in GL (as we do 'late' ID creation) */
	    gltex_get_tex_name(surf_ptr);
424 425 426 427 428 429
	    glBindTexture(GL_TEXTURE_2D, gl_surf_ptr->tex_name);
	    
	    if ((gl_surf_ptr->dirty_flag == SURFACE_MEMORY_DIRTY) &&
		!((dstx == 0) && (dsty == 0) &&
		  (width == surf_ptr->surface_desc.dwWidth) && (height == surf_ptr->surface_desc.dwHeight))) {
		/* If not 'full size' and the surface is dirty, first flush it to GL before doing the copy. */
430
	        if (upload_surface_to_tex_memory_init(surf_ptr, surf_ptr->mipmap_level, &(gl_surf_ptr->current_internal_format),
431
						      gl_surf_ptr->initial_upload_done == FALSE, TRUE, 0, 0) == DD_OK) {
432
		    upload_surface_to_tex_memory(NULL, 0, 0, &(gl_surf_ptr->surface_ptr));
433 434
		    upload_surface_to_tex_memory_release();
		    gl_surf_ptr->dirty_flag = SURFACE_MEMORY;
435
		    gl_surf_ptr->initial_upload_done = TRUE;
436
		} else {
437 438 439
		    glBindTexture(GL_TEXTURE_2D, cur_tex);
		    LEAVE_GL();
		    ERR("Error at texture upload !\n");
440 441
		    return DDERR_INVALIDPARAMS;
		}
442 443 444 445
	    }

	    /* This is a hack and would need some clean-up :-) */
	    if (gl_surf_ptr->initial_upload_done == FALSE) {
446
		if (upload_surface_to_tex_memory_init(surf_ptr, surf_ptr->mipmap_level, &(gl_surf_ptr->current_internal_format),
447
						      TRUE, TRUE, 0, 0) == DD_OK) {
448
		    upload_surface_to_tex_memory(NULL, 0, 0, &(gl_surf_ptr->surface_ptr));
449 450
		    upload_surface_to_tex_memory_release();
		    gl_surf_ptr->dirty_flag = SURFACE_MEMORY;
451
		    gl_surf_ptr->initial_upload_done = TRUE;
452
		} else {
453 454 455
		    glBindTexture(GL_TEXTURE_2D, cur_tex);
		    LEAVE_GL();
		    ERR("Error at texture upload (initial case) !\n");
456 457
		    return DDERR_INVALIDPARAMS;
		}
458 459 460 461 462 463 464 465
	    }
	    
	    if ((src_ptr->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0)
		glReadBuffer(GL_FRONT);
	    else if ((src_ptr->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER))
		glReadBuffer(GL_BACK);
	    else {
		ERR("Wrong surface type for locking !\n");
466
		glBindTexture(GL_TEXTURE_2D, cur_tex);
467 468 469 470
		LEAVE_GL();
		return DDERR_INVALIDPARAMS;
	    }
	    
471
	    for (y = (src_ptr->surface_desc.dwHeight - rsrc->top - 1);
472 473 474 475 476 477 478 479 480 481 482 483
		 y >= (src_ptr->surface_desc.dwHeight - (rsrc->top + height));
		 y--) {
		glCopyTexSubImage2D(GL_TEXTURE_2D, surf_ptr->mipmap_level,
				    dstx, dsty,
				    rsrc->left, y,
				    width, 1);
		dsty++;
	    }
	    
	    glBindTexture(GL_TEXTURE_2D, cur_tex);
	    LEAVE_GL();
	    
484
	    /* The SURFACE_GL case is not handled by the 'global' dirty flag */
485 486 487 488 489 490 491 492
	    gl_surf_ptr->dirty_flag = SURFACE_GL;
	    
	    return DD_OK;
	}
    }
    return DDERR_INVALIDPARAMS;
}

493 494 495 496
HRESULT WINAPI
Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
                                              DWORD dwStart,
                                              DWORD dwCount)
497
{
498
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
499 500
    FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
    return DD_OK;
501 502
}

503 504
HRESULT WINAPI
Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
505
{
506
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
507 508
    FIXME("(%p/%p)->(): stub!\n", This, iface);
    return DD_OK;
509 510
}

511 512 513 514
HRESULT WINAPI
Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
					 LPDIRECT3DDEVICE2 lpDirect3DDevice2,
					 LPD3DTEXTUREHANDLE lpHandle)
515
{
516
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
517 518 519 520 521 522 523 524 525 526 527 528 529
    IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
    
    TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);

    /* The handle is simply the pointer to the implementation structure */
    *lpHandle = (D3DTEXTUREHANDLE) This;

    TRACE(" returning handle %08lx.\n", *lpHandle);
    
    /* Now set the device for this texture */
    This->d3ddevice = lpDeviceImpl;

    return D3D_OK;
530 531
}

532 533 534
HRESULT WINAPI
Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
				    LPDIRECT3DTEXTURE2 lpD3DTexture2)
535
{
536
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
537 538
    FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
    return DD_OK;
539 540
}

541 542 543
static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal)
{
    IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
544 545

    if (glThis->dirty_flag == SURFACE_GL) {
Mike McCormack's avatar
Mike McCormack committed
546
	GLint cur_tex;
547
	
548 549
	TRACE(" flushing GL texture back to memory.\n");
	
550 551 552
	ENTER_GL();
	glGetIntegerv(GL_TEXTURE_BINDING_2D, &cur_tex);
	glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
553
	gltex_download_texture(This);
554 555 556
	glBindTexture(GL_TEXTURE_2D, cur_tex);
	LEAVE_GL();
    }
557 558 559
    
    /* First call the previous set_palette function */
    glThis->set_palette(This, pal);
560 561
    
    /* And set the dirty flag */
562
    glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
563
    *(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
564 565 566
    
    /* TODO: check palette on mipmapped surfaces...
       TODO: do we need to re-upload in case of usage of the paletted texture extension ? */
567 568
}

569 570
static void
gltex_final_release(IDirectDrawSurfaceImpl *This)
571
{
572 573
    IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
    DWORD mem_used;
574
    int i;
575

576
    TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
577

578 579 580 581 582 583
    /* And delete texture handle */
    ENTER_GL();
    if (glThis->tex_name != 0)
        glDeleteTextures(1, &(glThis->tex_name));
    LEAVE_GL();	

584
    HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
585

586 587
    /* And if this texture was the current one, remove it at the device level */
    if (This->d3ddevice != NULL)
588 589 590
        for (i = 0; i < MAX_TEXTURES; i++)
	    if (This->d3ddevice->current_texture[i] == This)
	        This->d3ddevice->current_texture[i] = NULL;
591 592 593 594

    /* All this should be part of main surface management not just a hack for texture.. */
    if (glThis->loaded) {
        mem_used = This->surface_desc.dwHeight *
595
	           This->surface_desc.u1.lPitch;
596
	This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
597
    }
598

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    glThis->final_release(This);
}

static void
gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
{
    IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
    
    glThis->lock_update(This, pRect, dwFlags);
}

static void
gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
{
    IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;

615 616
    glThis->unlock_update(This, pRect);
    
617
    /* Set the dirty flag according to the lock type */
618
    if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
619
        glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
620 621
	*(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
    }
622 623
}

624 625 626 627
HRESULT WINAPI
GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
				  LPDIRECT3DTEXTURE2 lpD3DTexture2)
{
628
    ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
629 630
    IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
    IDirectDrawSurfaceImpl *dst_ptr = This;
631
    HRESULT ret_value = D3D_OK;
632
   
633
    TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
634

635 636 637 638 639 640 641 642 643 644 645 646 647
    if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
	(src_ptr->surface_desc.u2.dwMipMapCount != dst_ptr->surface_desc.u2.dwMipMapCount)) {
        ERR("Trying to load surfaces with different mip-map counts !\n");
    }

    /* Now loop through all mipmap levels and load all of them... */
    while (1) {
        IDirect3DTextureGLImpl *gl_dst_ptr = (IDirect3DTextureGLImpl *) dst_ptr->tex_private;
	DDSURFACEDESC *src_d, *dst_d;
	
	if (gl_dst_ptr != NULL) {
	    if (gl_dst_ptr->loaded == FALSE) {
	        /* Only check memory for not already loaded texture... */
648 649 650 651 652
	        DWORD mem_used;
		if (dst_ptr->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
                    mem_used = dst_ptr->surface_desc.u1.dwLinearSize;
		else
                    mem_used = dst_ptr->surface_desc.dwHeight * dst_ptr->surface_desc.u1.lPitch;
653 654 655 656
		if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
		    TRACE(" out of virtual memory... Warning application.\n");
		    return D3DERR_TEXTURE_LOAD_FAILED;
		}
657
	    }
658
	    gl_dst_ptr->loaded = TRUE;
659
	}
660
    
661
	TRACE(" copying surface %p to surface %p (mipmap level %d)\n", src_ptr, dst_ptr, src_ptr->mipmap_level);
662

663 664 665 666 667
	if ( dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
	    /* If the surface is not allocated and its location is not yet specified,
	       force it to video memory */ 
	    if ( !(dst_ptr->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
	        dst_ptr->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
668

669 670
	/* Suppress the ALLOCONLOAD flag */
	dst_ptr->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
671
    
672 673 674 675 676 677 678 679 680 681 682 683
	/* After seeing some logs, not sure at all about this... */
	if (dst_ptr->palette == NULL) {
	    dst_ptr->palette = src_ptr->palette;
	    if (src_ptr->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(src_ptr->palette, IDirectDrawPalette));
	} else {
	    if (src_ptr->palette != NULL) {
	        PALETTEENTRY palent[256];
		IDirectDrawPalette_GetEntries(ICOM_INTERFACE(src_ptr->palette, IDirectDrawPalette),
					      0, 0, 256, palent);
		IDirectDrawPalette_SetEntries(ICOM_INTERFACE(dst_ptr->palette, IDirectDrawPalette),
					      0, 0, 256, palent);
	    }
684
	}
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
	
	/* Copy one surface on the other */
	dst_d = (DDSURFACEDESC *)&(dst_ptr->surface_desc);
	src_d = (DDSURFACEDESC *)&(src_ptr->surface_desc);

	if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
	    /* Should also check for same pixel format, u1.lPitch, ... */
	    ERR("Error in surface sizes\n");
	    return D3DERR_TEXTURE_LOAD_FAILED;
	} else {
	    /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
	    /* I should put a macro for the calculus of bpp */
	  
	    /* Copy also the ColorKeying stuff */
	    if (src_d->dwFlags & DDSD_CKSRCBLT) {
	        dst_d->dwFlags |= DDSD_CKSRCBLT;
		dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
		dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
	    }
Jeff Garzik's avatar
Jeff Garzik committed
704

705 706
	    /* Copy the main memory texture into the surface that corresponds to the OpenGL
	       texture object. */
707 708 709 710
	    if (dst_ptr->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
	        memcpy(dst_d->lpSurface, src_d->lpSurface, src_ptr->surface_desc.u1.dwLinearSize);
	    else
	        memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
711

712 713
	    if (gl_dst_ptr != NULL) {
		/* Set this texture as dirty */
714
		gl_dst_ptr->dirty_flag = SURFACE_MEMORY_DIRTY;
715
		*(gl_dst_ptr->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
716 717 718
	    }
	}

719 720 721 722 723 724 725 726 727 728
	if (src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
	    src_ptr = get_sub_mimaplevel(src_ptr);
	} else {
	    src_ptr = NULL;
	}
	if (dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
	    dst_ptr = get_sub_mimaplevel(dst_ptr);
	} else {
	    dst_ptr = NULL;
	}
729 730 731 732 733 734

	if ((src_ptr == NULL) || (dst_ptr == NULL)) {
	    if (src_ptr != dst_ptr) {
	        ERR(" Loading surface with different mipmap structure !!!\n");
	    }
	    break;
735
	}
736
    }
737

738
    return ret_value;
739
}
740

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
HRESULT WINAPI
Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
                                            REFIID riid,
                                            LPVOID* obp)
{
    TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
    return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
					      riid,
					      obp);
}

ULONG WINAPI
Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
{
    TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
    return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
}

ULONG WINAPI
Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
{
    TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
763
    return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
764 765
}

766 767 768 769 770
HRESULT WINAPI
Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
                                            REFIID riid,
                                            LPVOID* obp)
{
771 772 773 774
    TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
    return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
					      riid,
					      obp);
775
}
776

777 778 779
ULONG WINAPI
Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
{
780 781
    TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
    return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
782
}
783

784 785 786
ULONG WINAPI
Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
{
787
    TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
788
    return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
789
}
790

791 792 793 794 795 796
HRESULT WINAPI
Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
                                            DWORD dwStart,
                                            DWORD dwCount)
{
    TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
797
    return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
798 799 800
                                            dwStart,
                                            dwCount);
}
801

802 803 804 805 806 807
HRESULT WINAPI
Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
				       LPDIRECT3DDEVICE lpDirect3DDevice,
				       LPD3DTEXTUREHANDLE lpHandle)
{
    TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
808
    return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
809 810 811
				       COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
				       lpHandle);
}
812

813 814 815 816 817
HRESULT WINAPI
Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
				  LPDIRECT3DTEXTURE lpD3DTexture)
{
    TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
818 819
    return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
				  COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
820 821
}

822 823 824 825 826
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun)     (typeof(VTABLE_IDirect3DTexture2.fun))
#else
# define XCAST(fun)     (void*)
#endif
827

828
static const IDirect3DTexture2Vtbl VTABLE_IDirect3DTexture2 =
829
{
830 831 832
    XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
    XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
    XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
833
    XCAST(GetHandle) Main_IDirect3DTextureImpl_2_1T_GetHandle,
834 835
    XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
    XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
836 837
};

838
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
839 840 841 842 843 844
#undef XCAST
#endif


#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun)     (typeof(VTABLE_IDirect3DTexture.fun))
845
#else
846
# define XCAST(fun)     (void*)
847 848
#endif

849
static const IDirect3DTextureVtbl VTABLE_IDirect3DTexture =
850
{
851 852 853 854 855 856 857 858
    XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
    XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
    XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
    XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
    XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
    XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
    XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
    XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
859
};
860 861 862 863

#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
#undef XCAST
#endif
864

865
HRESULT d3dtexture_create(IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation, 
866
			  IDirectDrawSurfaceImpl *main)
867
{
868
    /* First, initialize the texture vtables... */
869 870
    ICOM_INIT_INTERFACE(surf, IDirect3DTexture,  VTABLE_IDirect3DTexture);
    ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
871 872
	
    /* Only create all the private stuff if we actually have an OpenGL context.. */
873
    if (d3d->current_device != NULL) {
874
        IDirect3DTextureGLImpl *private;
875

876 877 878
        private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
	if (private == NULL) return DDERR_OUTOFMEMORY;

879 880
	surf->tex_private = private;
	
881 882 883
	private->final_release = surf->final_release;
	private->lock_update = surf->lock_update;
	private->unlock_update = surf->unlock_update;
884
	private->set_palette = surf->set_palette;
885 886 887 888 889 890
	
	/* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
	   Otherwise, it will be uploaded here (and may be invalid). */
	surf->final_release = gltex_final_release;
	surf->lock_update = gltex_lock_update;
	surf->unlock_update = gltex_unlock_update;
891
	surf->aux_setcolorkey_cb = gltex_setcolorkey_cb;
892 893
	surf->set_palette = gltex_set_palette;

894
	/* We are the only one to use the aux_blt and aux_bltfast overrides, so no need
895 896 897
	   to save those... */
	surf->aux_blt = gltex_blt;
	surf->aux_bltfast = gltex_bltfast;
898 899
	
	TRACE(" GL texture created for surface %p (private data at %p)\n", surf, private);
900 901 902 903 904 905

	/* Do not create the OpenGL texture id here as some game generate textures from a different thread which
	    cause problems.. */
	private->tex_name = 0;
	if (surf->mipmap_level == 0) {
	    private->main = NULL;
906
	    private->__global_dirty_flag = SURFACE_MEMORY_DIRTY;
907 908 909 910 911 912
	    private->global_dirty_flag = &(private->__global_dirty_flag);
	} else {
	    private->main = main;
	    private->global_dirty_flag = &(((IDirect3DTextureGLImpl *) (private->main->tex_private))->__global_dirty_flag);
	}
	private->initial_upload_done = FALSE;
913
	private->dirty_flag = SURFACE_MEMORY_DIRTY;
914 915 916 917 918 919 920 921 922 923 924
    }

    return D3D_OK;
}

GLuint gltex_get_tex_name(IDirectDrawSurfaceImpl *surf)
{
    IDirect3DTextureGLImpl *private = (IDirect3DTextureGLImpl *) (surf->tex_private);
    
    if (private->tex_name == 0) {
	/* The texture was not created yet... */	
925 926 927 928
	ENTER_GL();
	if (surf->mipmap_level == 0) {
	    glGenTextures(1, &(private->tex_name));
	    if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
929
	    TRACE(" GL texture id is : %d.\n", private->tex_name);
930
	} else {
931 932
	    private->tex_name = gltex_get_tex_name(private->main);
	    TRACE(" GL texture id reusing id %d from surface %p (private at %p)).\n", private->tex_name, private->main, private->main->tex_private);
933 934
	}
	LEAVE_GL();
935
    }
936
    return ((IDirect3DTextureGLImpl *) (surf->tex_private))->tex_name;
937
}