1 /* 2 * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #ifndef HEADLESS 27 28 #import "VertexDataManager.h" 29 #import <Metal/Metal.h> 30 31 32 33 static int MAX_PRIMITIVES = 100; //TODO : this needs to be changed to dynamic array of structures to support any number of primitives 34 35 // TODO : all static members should be class members when singleton is implemented 36 static id<MTLBuffer> VertexBuffer; 37 static id<MTLBuffer> IndexBuffer; 38 static unsigned int no_of_vertices = 0; 39 static unsigned int no_of_indices = 0; 40 static unsigned int no_of_primitives = 0; 41 MetalPrimitiveData** AllPrimitives = NULL; 42 43 44 void VertexDataManager_init(id<MTLDevice> device) { 45 // This limited buffer size allocation is for PoC purpose. 46 // TODO : Need to implement a logic where we allocate more chunks if needed 47 48 VertexBuffer = [device newBufferWithLength:1024 * 32 options:MTLResourceOptionCPUCacheModeDefault]; 49 IndexBuffer = [device newBufferWithLength:1024 * 8 options:MTLResourceOptionCPUCacheModeDefault]; 50 51 AllPrimitives = (MetalPrimitiveData**) malloc(sizeof(MetalPrimitiveData*) * MAX_PRIMITIVES); //[[NSMutableArray<MetalPrimitiveData*> alloc] init]; 52 } 53 54 void VertexDataManager_addLineVertexData(MetalVertex v1, MetalVertex v2) { 55 56 // Create a structure of MetalPrimitiveData (populate it) and it to the array 57 MetalPrimitiveData* data = (MetalPrimitiveData*) malloc(sizeof(MetalPrimitiveData));//[[MetalPrimitiveData alloc] init]; 58 data->type = MTLPrimitiveTypeLine; 59 data->offset_in_index_buffer = (no_of_indices) * sizeof(unsigned short); 60 data->no_of_indices = 2; 61 data->primitiveInstances = 1; 62 63 AllPrimitives[no_of_primitives] = data; 64 no_of_primitives++; 65 66 // Add v1, v2 to VertexBuffer 67 addIndex(no_of_vertices); 68 69 addVertex(v1); 70 71 addIndex(no_of_vertices); 72 73 addVertex(v2); 74 } 75 76 void VertexDataManager_addQuadVertexData(MetalVertex v1, MetalVertex v2, MetalVertex v3, MetalVertex v4) { 77 78 MetalPrimitiveData* data = (MetalPrimitiveData*) malloc(sizeof(MetalPrimitiveData));//[[MetalPrimitiveData alloc] init]; 79 data->type = MTLPrimitiveTypeTriangle; 80 data->offset_in_index_buffer = (no_of_indices) * sizeof(unsigned short); 81 data->no_of_indices = 6; 82 data->primitiveInstances = 2; 83 84 AllPrimitives[no_of_primitives] = data; 85 no_of_primitives++; 86 87 // Add all 4 vertices to the Vertexbuffer 88 unsigned int firstVertexNumber = no_of_vertices; 89 90 addVertex(v1); 91 addVertex(v2); 92 addVertex(v3); 93 addVertex(v4); 94 95 /* 96 v1-------v4 97 | \ | 98 | \ | 99 | \ | 100 | \ | 101 | \ | 102 | \ | 103 | \| 104 v2-------v3 105 */ 106 107 // A quad is made up of two triangles 108 // Order of vertices is important - it is counter-clockwise 109 // Specify 2 set of triangles using 3 indices each 110 addIndex(firstVertexNumber); // v1 111 addIndex(firstVertexNumber + 1); // v2 112 addIndex(firstVertexNumber + 2); // v3 113 114 addIndex(firstVertexNumber + 2); // v3 115 addIndex(firstVertexNumber + 3); // v4 116 addIndex(firstVertexNumber); // v1 117 } 118 119 void addVertex(MetalVertex vert) { 120 memcpy(VertexBuffer.contents + (no_of_vertices * sizeof(MetalVertex)), &vert, sizeof(MetalVertex)); 121 no_of_vertices++; 122 } 123 124 void addIndex(unsigned short vertexNum) { 125 memcpy(IndexBuffer.contents + no_of_indices * sizeof(unsigned short), &vertexNum, sizeof(unsigned short)); 126 no_of_indices++; 127 } 128 129 130 id<MTLBuffer> VertexDataManager_getVertexBuffer() { 131 return VertexBuffer; 132 } 133 134 id<MTLBuffer> VertexDataManager_getIndexBuffer() { 135 return IndexBuffer; 136 } 137 138 MetalPrimitiveData** VertexDataManager_getAllPrimitives() { 139 return AllPrimitives; 140 } 141 142 unsigned int VertexDataManager_getNoOfPrimitives() { 143 return no_of_primitives; 144 } 145 146 void VertexDataManager_freeAllPrimitives() { 147 148 for (int i = 0; i < no_of_primitives; i++) { 149 free(AllPrimitives[i]); 150 } 151 152 free(AllPrimitives); 153 } 154 155 void VertexDataManager_reset(id<MTLDevice> device) { 156 VertexDataManager_freeAllPrimitives(); 157 VertexBuffer = NULL; 158 IndexBuffer = NULL; 159 no_of_vertices = 0; 160 no_of_indices = 0; 161 no_of_primitives = 0; 162 AllPrimitives = NULL; 163 VertexDataManager_init(device); 164 } 165 166 #endif /* !HEADLESS */