1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
8 
9 #include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
10 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
11 
12 namespace rx
13 {
14 
IndexBuffer9(Renderer9 * const renderer)15 IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
16 {
17     mIndexBuffer = nullptr;
18     mBufferSize = 0;
19     mIndexType = 0;
20     mDynamic = false;
21 }
22 
~IndexBuffer9()23 IndexBuffer9::~IndexBuffer9()
24 {
25     SafeRelease(mIndexBuffer);
26 }
27 
initialize(unsigned int bufferSize,GLenum indexType,bool dynamic)28 gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
29 {
30     SafeRelease(mIndexBuffer);
31 
32     updateSerial();
33 
34     if (bufferSize > 0)
35     {
36         D3DFORMAT format = D3DFMT_UNKNOWN;
37         if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
38         {
39             format = D3DFMT_INDEX16;
40         }
41         else if (indexType == GL_UNSIGNED_INT)
42         {
43             ASSERT(mRenderer->getNativeExtensions().elementIndexUint);
44             format = D3DFMT_INDEX32;
45         }
46         else UNREACHABLE();
47 
48         DWORD usageFlags = D3DUSAGE_WRITEONLY;
49         if (dynamic)
50         {
51             usageFlags |= D3DUSAGE_DYNAMIC;
52         }
53 
54         HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
55         if (FAILED(result))
56         {
57             return gl::OutOfMemory()
58                    << "Failed to allocate internal index buffer of size " << bufferSize;
59         }
60     }
61 
62     mBufferSize = bufferSize;
63     mIndexType = indexType;
64     mDynamic = dynamic;
65 
66     return gl::NoError();
67 }
68 
mapBuffer(unsigned int offset,unsigned int size,void ** outMappedMemory)69 gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
70 {
71     if (!mIndexBuffer)
72     {
73         return gl::OutOfMemory() << "Internal index buffer is not initialized.";
74     }
75 
76     DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
77 
78     void *mapPtr   = nullptr;
79     HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
80     if (FAILED(result))
81     {
82         return gl::OutOfMemory() << "Failed to lock internal index buffer, " << gl::FmtHR(result);
83     }
84 
85     *outMappedMemory = mapPtr;
86     return gl::NoError();
87 }
88 
unmapBuffer()89 gl::Error IndexBuffer9::unmapBuffer()
90 {
91     if (!mIndexBuffer)
92     {
93         return gl::OutOfMemory() << "Internal index buffer is not initialized.";
94     }
95 
96     HRESULT result = mIndexBuffer->Unlock();
97     if (FAILED(result))
98     {
99         return gl::OutOfMemory() << "Failed to unlock internal index buffer, " << gl::FmtHR(result);
100     }
101 
102     return gl::NoError();
103 }
104 
getIndexType() const105 GLenum IndexBuffer9::getIndexType() const
106 {
107     return mIndexType;
108 }
109 
getBufferSize() const110 unsigned int IndexBuffer9::getBufferSize() const
111 {
112     return mBufferSize;
113 }
114 
setSize(unsigned int bufferSize,GLenum indexType)115 gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
116 {
117     if (bufferSize > mBufferSize || indexType != mIndexType)
118     {
119         return initialize(bufferSize, indexType, mDynamic);
120     }
121     else
122     {
123         return gl::NoError();
124     }
125 }
126 
discard()127 gl::Error IndexBuffer9::discard()
128 {
129     if (!mIndexBuffer)
130     {
131         return gl::OutOfMemory() << "Internal index buffer is not initialized.";
132     }
133 
134     void *dummy;
135     HRESULT result;
136 
137     result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
138     if (FAILED(result))
139     {
140         return gl::OutOfMemory() << "Failed to lock internal index buffer, " << gl::FmtHR(result);
141     }
142 
143     result = mIndexBuffer->Unlock();
144     if (FAILED(result))
145     {
146         return gl::OutOfMemory() << "Failed to unlock internal index buffer, " << gl::FmtHR(result);
147     }
148 
149     return gl::NoError();
150 }
151 
getIndexFormat() const152 D3DFORMAT IndexBuffer9::getIndexFormat() const
153 {
154     switch (mIndexType)
155     {
156       case GL_UNSIGNED_BYTE:    return D3DFMT_INDEX16;
157       case GL_UNSIGNED_SHORT:   return D3DFMT_INDEX16;
158       case GL_UNSIGNED_INT:     return D3DFMT_INDEX32;
159       default: UNREACHABLE();   return D3DFMT_UNKNOWN;
160     }
161 }
162 
getBuffer() const163 IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
164 {
165     return mIndexBuffer;
166 }
167 
168 }
169