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