1 //
2 // Copyright (c) 2012 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 // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
8 
9 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
10 
11 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
12 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
13 
14 namespace rx
15 {
16 
IndexBuffer11(Renderer11 * const renderer)17 IndexBuffer11::IndexBuffer11(Renderer11 *const renderer)
18     : mRenderer(renderer), mBuffer(), mBufferSize(0), mIndexType(GL_NONE), mDynamicUsage(false)
19 {
20 }
21 
~IndexBuffer11()22 IndexBuffer11::~IndexBuffer11()
23 {
24 }
25 
initialize(unsigned int bufferSize,GLenum indexType,bool dynamic)26 gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
27 {
28     mBuffer.reset();
29 
30     updateSerial();
31 
32     if (bufferSize > 0)
33     {
34         D3D11_BUFFER_DESC bufferDesc;
35         bufferDesc.ByteWidth = bufferSize;
36         bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
37         bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
38         bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
39         bufferDesc.MiscFlags = 0;
40         bufferDesc.StructureByteStride = 0;
41 
42         ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer));
43 
44         if (dynamic)
45         {
46             mBuffer.setDebugName("IndexBuffer11 (dynamic)");
47         }
48         else
49         {
50             mBuffer.setDebugName("IndexBuffer11 (static)");
51         }
52     }
53 
54     mBufferSize = bufferSize;
55     mIndexType = indexType;
56     mDynamicUsage = dynamic;
57 
58     return gl::NoError();
59 }
60 
mapBuffer(unsigned int offset,unsigned int size,void ** outMappedMemory)61 gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
62 {
63     if (!mBuffer.valid())
64     {
65         return gl::OutOfMemory() << "Internal index buffer is not initialized.";
66     }
67 
68     // Check for integer overflows and out-out-bounds map requests
69     if (offset + size < offset || offset + size > mBufferSize)
70     {
71         return gl::OutOfMemory() << "Index buffer map range is not inside the buffer.";
72     }
73 
74     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
75 
76     D3D11_MAPPED_SUBRESOURCE mappedResource;
77     HRESULT result =
78         dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
79     if (FAILED(result))
80     {
81         return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result);
82     }
83 
84     *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
85     return gl::NoError();
86 }
87 
unmapBuffer()88 gl::Error IndexBuffer11::unmapBuffer()
89 {
90     if (!mBuffer.valid())
91     {
92         return gl::OutOfMemory() << "Internal index buffer is not initialized.";
93     }
94 
95     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
96     dxContext->Unmap(mBuffer.get(), 0);
97     return gl::NoError();
98 }
99 
getIndexType() const100 GLenum IndexBuffer11::getIndexType() const
101 {
102     return mIndexType;
103 }
104 
getBufferSize() const105 unsigned int IndexBuffer11::getBufferSize() const
106 {
107     return mBufferSize;
108 }
109 
setSize(unsigned int bufferSize,GLenum indexType)110 gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
111 {
112     if (bufferSize > mBufferSize || indexType != mIndexType)
113     {
114         return initialize(bufferSize, indexType, mDynamicUsage);
115     }
116     else
117     {
118         return gl::NoError();
119     }
120 }
121 
discard()122 gl::Error IndexBuffer11::discard()
123 {
124     if (!mBuffer.valid())
125     {
126         return gl::OutOfMemory() << "Internal index buffer is not initialized.";
127     }
128 
129     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
130 
131     D3D11_MAPPED_SUBRESOURCE mappedResource;
132     HRESULT result = dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
133     if (FAILED(result))
134     {
135         return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result);
136     }
137 
138     dxContext->Unmap(mBuffer.get(), 0);
139 
140     return gl::NoError();
141 }
142 
getIndexFormat() const143 DXGI_FORMAT IndexBuffer11::getIndexFormat() const
144 {
145     switch (mIndexType)
146     {
147       case GL_UNSIGNED_BYTE:    return DXGI_FORMAT_R16_UINT;
148       case GL_UNSIGNED_SHORT:   return DXGI_FORMAT_R16_UINT;
149       case GL_UNSIGNED_INT:     return DXGI_FORMAT_R32_UINT;
150       default: UNREACHABLE();   return DXGI_FORMAT_UNKNOWN;
151     }
152 }
153 
getBuffer() const154 const d3d11::Buffer &IndexBuffer11::getBuffer() const
155 {
156     return mBuffer;
157 }
158 
159 }  // namespace rx
160