We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2625

Summary: Direct3D9 with SDL_TEXTUREACCESS_TARGET textures causes an application crash
Product: SDL Reporter: Roberto Prieto <dm2>
Component: renderAssignee: Sam Lantinga <slouken>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: icculus, rush
Version: 2.0.3   
Hardware: x86   
OS: Windows 7   

Description Roberto Prieto 2014-07-04 19:03:10 UTC
Hi,

when using Direct3D9 with SDL_TEXTUREACCESS_TARGET textures, my application just crash when using SDL_UpdateTexture().

After debugging the code I think changes implemented on:

Sat, 31 May 2014 11:37:12 -0700 (4 weeks ago)
Use D3D9Ex when available
This hopefully works around crashes in Intel D3D9 support in Windows 8.1. 

causes the crash and it is related with this structure:

typedef struct
{
    SDL_bool dirty;
    IDirect3DTexture9 *texture;
    IDirect3DTexture9 *staging;
} D3D_TextureRep;

and the new staging texture.

Let's explain it:

- when a texture is created:
static int D3D_CreateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWORD usage, Uint32 format, int w, int h)
{
    HRESULT result;

    texture->dirty = SDL_FALSE;

    result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
        PixelFormatToD3DFMT(format),
        D3DPOOL_DEFAULT, &texture->texture, NULL);
    if (FAILED(result)) {
        return D3D_SetError("CreateTexture(D3DPOOL_DEFAULT)", result);
    }

    if (usage != D3DUSAGE_RENDERTARGET) {
        result = IDirect3DDevice9_CreateTexture(device, w, h, 1, usage,
            PixelFormatToD3DFMT(format),
            D3DPOOL_SYSTEMMEM, &texture->staging, NULL);
        if (FAILED(result)) {
            return D3D_SetError("CreateTexture(D3DPOOL_SYSTEMMEM)", result);
        }
    }
    return 0;
}

if SDL_TEXTUREACCESS_TARGET flag is used, the staging texture is not created and its value is NULL.

Later, there are functions that check if stating is not NULL but there are others that try to use is as:

static int D3D_UpdateTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, Uint32 format, int x, int y, int w, int h, const void *pixels, int pitch)
{
    RECT d3drect;
    D3DLOCKED_RECT locked;
    const Uint8 *src;
    Uint8 *dst;
    int row, length;
    HRESULT result;

    d3drect.left = x;
    d3drect.right = x + w;
    d3drect.top = y;
    d3drect.bottom = y + h;
    result = IDirect3DTexture9_LockRect(texture->staging, 0, &locked, &d3drect, 0);
    ...

This last call to IDirect3DTexture9_LockRect() caused the application crash as staging is set to NULL.

I think this check on D3D_CreateTextureRep():
if (usage != D3DUSAGE_RENDERTARGET) {

is not needed but dont have enough Direct3D knowledge for assuring it at 100%.
As soon as I replaced it with:
if(1) {

to force to create the staging memory even for SDL_TEXTUREACCESS_TARGET textures, the application does not crash anymore.
This could be the fix for this bug but... could anyone with better Direct3D knowledge validate it please?

Thanks in advance!
Regards

could anyone with better understanding of Direct
Comment 1 Roberto Prieto 2014-07-04 19:47:47 UTC
After doing more tests, it seems that the application does not crash because the call to create the staging texture just fail (no SDL_TEXTUREACCESS_TARGET textures can be created on D3DPOOL_SYSTEMMEM?).

And checking testrendertarget application, it does not suffer the same issue I have so I think the issue is on my code and not on SDL2.

I did several tests before opening the bug(obviously not enough..) so sorry, I didnt want to waste developers time.

Regards
Comment 2 Sam Lantinga 2014-07-08 04:42:32 UTC
Even if updating a target texture is invalid it still shouldn't crash. Thanks for the report! I'll look into it. :)
Comment 3 Damian Kaczmarek 2014-08-08 16:57:12 UTC
Possibly fixed by my patch to Bug 2677
Comment 4 Sam Lantinga 2014-08-17 06:19:13 UTC
Can you check to see if this fixes the issue for you?
https://hg.libsdl.org/SDL/rev/86a6f6d92960

Thanks!
Comment 5 Ryan C. Gordon 2015-02-19 02:55:18 UTC
Just pinging to see if we can close this bug with the changes Sam made, or if it needs further work.

--ryan.
Comment 6 Ryan C. Gordon 2015-02-19 06:32:16 UTC
Marking a large number of bugs with the "triage-2.0.4" keyword at once. Sorry
if you got a lot of email from this. This is to help me sort through some bugs
in regards to a 2.0.4 release. We may or may not fix this bug for 2.0.4,
though!
Comment 7 Roberto Prieto 2015-05-29 16:24:37 UTC
Hi,

During this weekend I will check if the issue was fixed.

Cheers
Roberto
Comment 8 Roberto Prieto 2015-05-29 22:12:49 UTC
Sam, Ryan,

I just checked it and with current SDL2 code when trying to use SDL_UpdateTexture() on a texture created with SDL_TEXTUREACCESS_TARGET, the application does not crash anymore on Direct3D mode (note OpenGL and software worked fine).

Of course, it still does not update the texture because it is not supported on Direct3D mode but no more crashes.

This bug is solved!!!

Thanks you very much!
Roberto

P.S.: <a src="https://bugzilla.libsdl.org/show_bug.cgi?id=2677">bug 2677</a> is also fixed as it is the same one.
Comment 9 Sam Lantinga 2015-05-30 03:26:00 UTC
Looking at the code I don't see any reason it shouldn't work for target textures. Can you grab the latest snapshot and debug why it doesn't work?
http://www.libsdl.org/tmp/SDL-2.0.zip

Thanks!
Comment 10 Ryan C. Gordon 2015-05-31 05:57:12 UTC
*** Bug 2677 has been marked as a duplicate of this bug. ***
Comment 11 Roberto Prieto 2015-06-03 19:55:57 UTC
Hi Sam,

I have debugged the code checking the function calls when Direct3D is the renderer, remember that with software and OpenGL renderers, this issue is not happening.

- Create the texture:
SDL_Texture *pTex = SDL_CreateTexture(pRenderer, iFormat, SDL_TEXTUREACCESS_TARGET, pSurf->w, pSurf->h);

- Update the texture:
SDL_UpdateTexture(pTex, NULL, pSurf->pixels, pSurf->pitch); 
  SDL_render.c, SDL_UpdateTexture(): return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
    SDL_render_d3d.c, D3D_UpdateTexture(): if (D3D_UpdateTextureRep(data->device, &texturedata->texture, texture->format, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {
      SDL_render_d3d.c, D3D_UpdateTextureRep(): if (D3D_CreateStagingTexture(device, texture) < 0) {
        SDL_render_d3d.c, D3D_CreateStagingTexture(): result = IDirect3DDevice9_CreateTexture(..., D3DPOOL_SYSTEMMEM, ...) --> FAIL! with INVALIDCALL code

After checking a bit the Microsoft documentation, I found this:

D3DUSAGE_RENDERTARGET can only be used with D3DPOOL_DEFAULT. (https://msdn.microsoft.com/en-us/library/windows/desktop/bb172625%28v=vs.85%29.aspx)

The call that fails, is using D3DUSAGE_RENDERTARGET with D3DPOOL_SYSTEMMEM which is unsupported, hence the INVALIDCALL return code.

In addition, I tried myself to modify that D3DPOOL_SYSTEMMEM by a D3DPOOL_DEFAULT, in this case, the texture creation is OK but a call to IDirect3DTexture9_LockRect() right after calling D3D_CreateStagingTexture() in D3D_UpdateTextureRep() causes the same issue, an INVALIDCALL and that is whatever Microsoft says:
Textures created with D3DPOOL_DEFAULT are not lockable. (https://msdn.microsoft.com/en-us/library/windows/desktop/bb205913%28v=vs.85%29.aspx)

Just guessing... should render target textures on direct3d renderer not use the staging texture creation for avoiding this issue? 

At this point, please let me know if I can help you on something else.
Cheers
Roberto
Comment 12 Sam Lantinga 2015-06-04 07:57:18 UTC
Okay, I think this is fixed in this commit:
https://hg.libsdl.org/SDL/rev/115bc7548a8d

Can you verify with the latest SDL snapshot?
http://www.libsdl.org/tmp/SDL-2.0.zip

Thanks!
Comment 13 Roberto Prieto 2015-06-04 12:05:39 UTC
Bingo!!!!

It is working fine! 

I tried with all my tests using different textures (static, streaming and target) and all of them worked fine.

Thanks you very much for your support!!!
Cheers
Roberto
Comment 14 Sam Lantinga 2015-06-06 22:46:14 UTC
You're very welcome! :)