1*c8dee2aaSAndroid Build Coastguard Worker/* 2*c8dee2aaSAndroid Build Coastguard Worker * This file houses utilities for copying blocks of memory to and from 3*c8dee2aaSAndroid Build Coastguard Worker * the WASM heap. 4*c8dee2aaSAndroid Build Coastguard Worker */ 5*c8dee2aaSAndroid Build Coastguard Worker 6*c8dee2aaSAndroid Build Coastguard Worker/** 7*c8dee2aaSAndroid Build Coastguard Worker * Malloc returns a TypedArray backed by the C++ memory of the 8*c8dee2aaSAndroid Build Coastguard Worker * given length. It should only be used by advanced users who 9*c8dee2aaSAndroid Build Coastguard Worker * can manage memory and initialize values properly. When used 10*c8dee2aaSAndroid Build Coastguard Worker * correctly, it can save copying of data between JS and C++. 11*c8dee2aaSAndroid Build Coastguard Worker * When used incorrectly, it can lead to memory leaks. 12*c8dee2aaSAndroid Build Coastguard Worker * Any memory allocated by CanvasKit.Malloc needs to be released with CanvasKit.Free. 13*c8dee2aaSAndroid Build Coastguard Worker * 14*c8dee2aaSAndroid Build Coastguard Worker * const mObj = CanvasKit.Malloc(Float32Array, 20); 15*c8dee2aaSAndroid Build Coastguard Worker * Get a TypedArray view around the malloc'd memory (this does not copy anything). 16*c8dee2aaSAndroid Build Coastguard Worker * const ta = mObj.toTypedArray(); 17*c8dee2aaSAndroid Build Coastguard Worker * // store data into ta 18*c8dee2aaSAndroid Build Coastguard Worker * const cf = CanvasKit.ColorFilter.MakeMatrix(ta); // mObj could also be used. 19*c8dee2aaSAndroid Build Coastguard Worker * 20*c8dee2aaSAndroid Build Coastguard Worker * // eventually... 21*c8dee2aaSAndroid Build Coastguard Worker * CanvasKit.Free(mObj); 22*c8dee2aaSAndroid Build Coastguard Worker * 23*c8dee2aaSAndroid Build Coastguard Worker * @param {TypedArray} typedArray - constructor for the typedArray. 24*c8dee2aaSAndroid Build Coastguard Worker * @param {number} len - number of *elements* to store. 25*c8dee2aaSAndroid Build Coastguard Worker */ 26*c8dee2aaSAndroid Build Coastguard WorkerCanvasKit.Malloc = function(typedArray, len) { 27*c8dee2aaSAndroid Build Coastguard Worker var byteLen = len * typedArray.BYTES_PER_ELEMENT; 28*c8dee2aaSAndroid Build Coastguard Worker var ptr = CanvasKit._malloc(byteLen); 29*c8dee2aaSAndroid Build Coastguard Worker return { 30*c8dee2aaSAndroid Build Coastguard Worker '_ck': true, 31*c8dee2aaSAndroid Build Coastguard Worker 'length': len, 32*c8dee2aaSAndroid Build Coastguard Worker 'byteOffset': ptr, 33*c8dee2aaSAndroid Build Coastguard Worker typedArray: null, 34*c8dee2aaSAndroid Build Coastguard Worker 'subarray': function(start, end) { 35*c8dee2aaSAndroid Build Coastguard Worker var sa = this['toTypedArray']().subarray(start, end); 36*c8dee2aaSAndroid Build Coastguard Worker sa['_ck'] = true; 37*c8dee2aaSAndroid Build Coastguard Worker return sa; 38*c8dee2aaSAndroid Build Coastguard Worker }, 39*c8dee2aaSAndroid Build Coastguard Worker 'toTypedArray': function() { 40*c8dee2aaSAndroid Build Coastguard Worker // Check if the previously allocated array is still usable. 41*c8dee2aaSAndroid Build Coastguard Worker // If it's falsy, then we haven't created an array yet. 42*c8dee2aaSAndroid Build Coastguard Worker // If it's empty, then WASM resized memory and emptied the array. 43*c8dee2aaSAndroid Build Coastguard Worker if (this.typedArray && this.typedArray.length) { 44*c8dee2aaSAndroid Build Coastguard Worker return this.typedArray; 45*c8dee2aaSAndroid Build Coastguard Worker } 46*c8dee2aaSAndroid Build Coastguard Worker this.typedArray = new typedArray(CanvasKit.HEAPU8.buffer, ptr, len); 47*c8dee2aaSAndroid Build Coastguard Worker // add a marker that this was allocated in C++ land 48*c8dee2aaSAndroid Build Coastguard Worker this.typedArray['_ck'] = true; 49*c8dee2aaSAndroid Build Coastguard Worker return this.typedArray; 50*c8dee2aaSAndroid Build Coastguard Worker }, 51*c8dee2aaSAndroid Build Coastguard Worker }; 52*c8dee2aaSAndroid Build Coastguard Worker}; 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker/** 55*c8dee2aaSAndroid Build Coastguard Worker * Free frees the memory returned by Malloc. 56*c8dee2aaSAndroid Build Coastguard Worker * Any memory allocated by CanvasKit.Malloc needs to be released with CanvasKit.Free. 57*c8dee2aaSAndroid Build Coastguard Worker */ 58*c8dee2aaSAndroid Build Coastguard WorkerCanvasKit.Free = function(mallocObj) { 59*c8dee2aaSAndroid Build Coastguard Worker CanvasKit._free(mallocObj['byteOffset']); 60*c8dee2aaSAndroid Build Coastguard Worker mallocObj['byteOffset'] = nullptr; 61*c8dee2aaSAndroid Build Coastguard Worker // Set these to null to make sure the TypedArrays can be garbage collected. 62*c8dee2aaSAndroid Build Coastguard Worker mallocObj['toTypedArray'] = null; 63*c8dee2aaSAndroid Build Coastguard Worker mallocObj.typedArray = null; 64*c8dee2aaSAndroid Build Coastguard Worker}; 65*c8dee2aaSAndroid Build Coastguard Worker 66*c8dee2aaSAndroid Build Coastguard Worker// This helper will free the given pointer unless the provided array is one 67*c8dee2aaSAndroid Build Coastguard Worker// that was returned by CanvasKit.Malloc. 68*c8dee2aaSAndroid Build Coastguard Workerfunction freeArraysThatAreNotMallocedByUsers(ptr, arr) { 69*c8dee2aaSAndroid Build Coastguard Worker if (!wasMalloced(arr)) { 70*c8dee2aaSAndroid Build Coastguard Worker CanvasKit._free(ptr); 71*c8dee2aaSAndroid Build Coastguard Worker } 72*c8dee2aaSAndroid Build Coastguard Worker} 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Worker// wasMalloced returns true if the object was created by a call to Malloc. This is determined 75*c8dee2aaSAndroid Build Coastguard Worker// by looking at a property that was added to our Malloc obj and typed arrays. 76*c8dee2aaSAndroid Build Coastguard Workerfunction wasMalloced(obj) { 77*c8dee2aaSAndroid Build Coastguard Worker return obj && obj['_ck']; 78*c8dee2aaSAndroid Build Coastguard Worker} 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker// We define some "scratch" variables which will house both the pointer to 81*c8dee2aaSAndroid Build Coastguard Worker// memory we allocate at startup as well as a Malloc object, which we can 82*c8dee2aaSAndroid Build Coastguard Worker// use to get a TypedArray view of that memory. 83*c8dee2aaSAndroid Build Coastguard Worker 84*c8dee2aaSAndroid Build Coastguard Workervar _scratch3x3MatrixPtr = nullptr; 85*c8dee2aaSAndroid Build Coastguard Workervar _scratch3x3Matrix; // the result from CanvasKit.Malloc 86*c8dee2aaSAndroid Build Coastguard Worker 87*c8dee2aaSAndroid Build Coastguard Workervar _scratch4x4MatrixPtr = nullptr; 88*c8dee2aaSAndroid Build Coastguard Workervar _scratch4x4Matrix; 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Workervar _scratchColorPtr = nullptr; 91*c8dee2aaSAndroid Build Coastguard Workervar _scratchColor; 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Workervar _scratchFourFloatsA; 94*c8dee2aaSAndroid Build Coastguard Workervar _scratchFourFloatsAPtr = nullptr; 95*c8dee2aaSAndroid Build Coastguard Worker 96*c8dee2aaSAndroid Build Coastguard Workervar _scratchFourFloatsB; 97*c8dee2aaSAndroid Build Coastguard Workervar _scratchFourFloatsBPtr = nullptr; 98*c8dee2aaSAndroid Build Coastguard Worker 99*c8dee2aaSAndroid Build Coastguard Workervar _scratchThreeFloatsA; 100*c8dee2aaSAndroid Build Coastguard Workervar _scratchThreeFloatsAPtr = nullptr; 101*c8dee2aaSAndroid Build Coastguard Worker 102*c8dee2aaSAndroid Build Coastguard Workervar _scratchThreeFloatsB; 103*c8dee2aaSAndroid Build Coastguard Workervar _scratchThreeFloatsBPtr = nullptr; 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Workervar _scratchIRect; 106*c8dee2aaSAndroid Build Coastguard Workervar _scratchIRectPtr = nullptr; 107*c8dee2aaSAndroid Build Coastguard Worker 108*c8dee2aaSAndroid Build Coastguard Workervar _scratchRRect; 109*c8dee2aaSAndroid Build Coastguard Workervar _scratchRRectPtr = nullptr; 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Workervar _scratchRRect2; 112*c8dee2aaSAndroid Build Coastguard Workervar _scratchRRect2Ptr = nullptr; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker// arr can be a normal JS array or a TypedArray 115*c8dee2aaSAndroid Build Coastguard Worker// dest is a string like 'HEAPU32' that specifies the type the src array 116*c8dee2aaSAndroid Build Coastguard Worker// should be copied into. 117*c8dee2aaSAndroid Build Coastguard Worker// ptr can be optionally provided if the memory was already allocated. 118*c8dee2aaSAndroid Build Coastguard Worker// Callers should eventually free the data unless the C++ object owns the memory, 119*c8dee2aaSAndroid Build Coastguard Worker// or the provided pointer is a scratch pointer or a user-malloced value. 120*c8dee2aaSAndroid Build Coastguard Worker// see also freeArraysThatAreNotMallocedByUsers(). 121*c8dee2aaSAndroid Build Coastguard Workerfunction copy1dArray(arr, dest, ptr) { 122*c8dee2aaSAndroid Build Coastguard Worker if (!arr || !arr.length) { 123*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 124*c8dee2aaSAndroid Build Coastguard Worker } 125*c8dee2aaSAndroid Build Coastguard Worker // This was created with CanvasKit.Malloc, so it's already been copied. 126*c8dee2aaSAndroid Build Coastguard Worker if (wasMalloced(arr)) { 127*c8dee2aaSAndroid Build Coastguard Worker return arr.byteOffset; 128*c8dee2aaSAndroid Build Coastguard Worker } 129*c8dee2aaSAndroid Build Coastguard Worker var bytesPerElement = CanvasKit[dest].BYTES_PER_ELEMENT; 130*c8dee2aaSAndroid Build Coastguard Worker if (!ptr) { 131*c8dee2aaSAndroid Build Coastguard Worker ptr = CanvasKit._malloc(arr.length * bytesPerElement); 132*c8dee2aaSAndroid Build Coastguard Worker } 133*c8dee2aaSAndroid Build Coastguard Worker // In c++ terms, the WASM heap is a uint8_t*, a long buffer/array of single 134*c8dee2aaSAndroid Build Coastguard Worker // byte elements. When we run _malloc, we always get an offset/pointer into 135*c8dee2aaSAndroid Build Coastguard Worker // that block of memory. 136*c8dee2aaSAndroid Build Coastguard Worker // CanvasKit exposes some different views to make it easier to work with 137*c8dee2aaSAndroid Build Coastguard Worker // different types. HEAPF32 for example, exposes it as a float* 138*c8dee2aaSAndroid Build Coastguard Worker // However, to make the ptr line up, we have to do some pointer arithmetic. 139*c8dee2aaSAndroid Build Coastguard Worker // Concretely, we need to convert ptr to go from an index into a 1-byte-wide 140*c8dee2aaSAndroid Build Coastguard Worker // buffer to an index into a 4-byte-wide buffer (in the case of HEAPF32) 141*c8dee2aaSAndroid Build Coastguard Worker // and thus we divide ptr by 4. 142*c8dee2aaSAndroid Build Coastguard Worker // It is important to make sure we are grabbing the freshest view of the 143*c8dee2aaSAndroid Build Coastguard Worker // memory possible because if we call _malloc and the heap needs to grow, 144*c8dee2aaSAndroid Build Coastguard Worker // the TypedArrayView will no longer be valid. 145*c8dee2aaSAndroid Build Coastguard Worker CanvasKit[dest].set(arr, ptr / bytesPerElement); 146*c8dee2aaSAndroid Build Coastguard Worker return ptr; 147*c8dee2aaSAndroid Build Coastguard Worker} 148*c8dee2aaSAndroid Build Coastguard Worker 149*c8dee2aaSAndroid Build Coastguard Worker// Copies an array of colors to wasm, returning an object with the pointer 150*c8dee2aaSAndroid Build Coastguard Worker// and info necessary to use the copied colors. 151*c8dee2aaSAndroid Build Coastguard Worker// Accepts either a flat Float32Array, flat Uint32Array or Array of Float32Arrays. 152*c8dee2aaSAndroid Build Coastguard Worker// If color is an object that was allocated with CanvasKit.Malloc, its pointer is 153*c8dee2aaSAndroid Build Coastguard Worker// returned and no extra copy is performed. 154*c8dee2aaSAndroid Build Coastguard Worker// TODO(nifong): have this accept color builders. 155*c8dee2aaSAndroid Build Coastguard Workerfunction copyFlexibleColorArray(colors) { 156*c8dee2aaSAndroid Build Coastguard Worker var result = { 157*c8dee2aaSAndroid Build Coastguard Worker colorPtr: nullptr, 158*c8dee2aaSAndroid Build Coastguard Worker count: colors.length, 159*c8dee2aaSAndroid Build Coastguard Worker colorType: CanvasKit.ColorType.RGBA_F32, 160*c8dee2aaSAndroid Build Coastguard Worker }; 161*c8dee2aaSAndroid Build Coastguard Worker if (colors instanceof Float32Array) { 162*c8dee2aaSAndroid Build Coastguard Worker result.colorPtr = copy1dArray(colors, 'HEAPF32'); 163*c8dee2aaSAndroid Build Coastguard Worker result.count = colors.length / 4; 164*c8dee2aaSAndroid Build Coastguard Worker 165*c8dee2aaSAndroid Build Coastguard Worker } else if (colors instanceof Uint32Array) { 166*c8dee2aaSAndroid Build Coastguard Worker result.colorPtr = copy1dArray(colors, 'HEAPU32'); 167*c8dee2aaSAndroid Build Coastguard Worker result.colorType = CanvasKit.ColorType.RGBA_8888; 168*c8dee2aaSAndroid Build Coastguard Worker 169*c8dee2aaSAndroid Build Coastguard Worker } else if (colors instanceof Array) { 170*c8dee2aaSAndroid Build Coastguard Worker result.colorPtr = copyColorArray(colors); 171*c8dee2aaSAndroid Build Coastguard Worker } else { 172*c8dee2aaSAndroid Build Coastguard Worker throw('Invalid argument to copyFlexibleColorArray, Not a color array '+typeof(colors)); 173*c8dee2aaSAndroid Build Coastguard Worker } 174*c8dee2aaSAndroid Build Coastguard Worker return result; 175*c8dee2aaSAndroid Build Coastguard Worker} 176*c8dee2aaSAndroid Build Coastguard Worker 177*c8dee2aaSAndroid Build Coastguard Workerfunction copyColorArray(arr) { 178*c8dee2aaSAndroid Build Coastguard Worker if (!arr || !arr.length) { 179*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 180*c8dee2aaSAndroid Build Coastguard Worker } 181*c8dee2aaSAndroid Build Coastguard Worker // 4 floats per color, 4 bytes per float. 182*c8dee2aaSAndroid Build Coastguard Worker var ptr = CanvasKit._malloc(arr.length * 4 * 4); 183*c8dee2aaSAndroid Build Coastguard Worker 184*c8dee2aaSAndroid Build Coastguard Worker var idx = 0; 185*c8dee2aaSAndroid Build Coastguard Worker var adjustedPtr = ptr / 4; // cast the byte pointer into a float pointer. 186*c8dee2aaSAndroid Build Coastguard Worker for (var r = 0; r < arr.length; r++) { 187*c8dee2aaSAndroid Build Coastguard Worker for (var c = 0; c < 4; c++) { 188*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.HEAPF32[adjustedPtr + idx] = arr[r][c]; 189*c8dee2aaSAndroid Build Coastguard Worker idx++; 190*c8dee2aaSAndroid Build Coastguard Worker } 191*c8dee2aaSAndroid Build Coastguard Worker } 192*c8dee2aaSAndroid Build Coastguard Worker return ptr; 193*c8dee2aaSAndroid Build Coastguard Worker} 194*c8dee2aaSAndroid Build Coastguard Worker 195*c8dee2aaSAndroid Build Coastguard Workervar defaultPerspective = Float32Array.of(0, 0, 1); 196*c8dee2aaSAndroid Build Coastguard Worker 197*c8dee2aaSAndroid Build Coastguard Worker// Copies the given DOMMatrix/Array/TypedArray to the CanvasKit heap and 198*c8dee2aaSAndroid Build Coastguard Worker// returns a pointer to the memory. This memory is a float* of length 9. 199*c8dee2aaSAndroid Build Coastguard Worker// If the passed in matrix is null/undefined, we return 0 (nullptr). The 200*c8dee2aaSAndroid Build Coastguard Worker// returned pointer should NOT be freed, as it is either null or a scratch 201*c8dee2aaSAndroid Build Coastguard Worker// pointer. 202*c8dee2aaSAndroid Build Coastguard Workerfunction copy3x3MatrixToWasm(matr) { 203*c8dee2aaSAndroid Build Coastguard Worker if (!matr) { 204*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 205*c8dee2aaSAndroid Build Coastguard Worker } 206*c8dee2aaSAndroid Build Coastguard Worker 207*c8dee2aaSAndroid Build Coastguard Worker var wasm3x3Matrix = _scratch3x3Matrix['toTypedArray'](); 208*c8dee2aaSAndroid Build Coastguard Worker if (matr.length) { 209*c8dee2aaSAndroid Build Coastguard Worker if (matr.length === 6 || matr.length === 9) { 210*c8dee2aaSAndroid Build Coastguard Worker // matr should be an array or typed array. 211*c8dee2aaSAndroid Build Coastguard Worker copy1dArray(matr, 'HEAPF32', _scratch3x3MatrixPtr); 212*c8dee2aaSAndroid Build Coastguard Worker if (matr.length === 6) { 213*c8dee2aaSAndroid Build Coastguard Worker // Overwrite the last 3 floats with the default perspective. The divide 214*c8dee2aaSAndroid Build Coastguard Worker // by 4 casts the pointer into a float pointer. 215*c8dee2aaSAndroid Build Coastguard Worker CanvasKit.HEAPF32.set(defaultPerspective, 6 + _scratch3x3MatrixPtr / 4); 216*c8dee2aaSAndroid Build Coastguard Worker } 217*c8dee2aaSAndroid Build Coastguard Worker return _scratch3x3MatrixPtr; 218*c8dee2aaSAndroid Build Coastguard Worker } else if (matr.length === 16) { 219*c8dee2aaSAndroid Build Coastguard Worker // Downsample the 4x4 matrix into a 3x3 220*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[0] = matr[0]; 221*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[1] = matr[1]; 222*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[2] = matr[3]; 223*c8dee2aaSAndroid Build Coastguard Worker 224*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[3] = matr[4]; 225*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[4] = matr[5]; 226*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[5] = matr[7]; 227*c8dee2aaSAndroid Build Coastguard Worker 228*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[6] = matr[12]; 229*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[7] = matr[13]; 230*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[8] = matr[15]; 231*c8dee2aaSAndroid Build Coastguard Worker return _scratch3x3MatrixPtr; 232*c8dee2aaSAndroid Build Coastguard Worker } 233*c8dee2aaSAndroid Build Coastguard Worker throw 'invalid matrix size'; 234*c8dee2aaSAndroid Build Coastguard Worker } else if (matr['m11'] === undefined) { 235*c8dee2aaSAndroid Build Coastguard Worker throw 'invalid matrix argument'; 236*c8dee2aaSAndroid Build Coastguard Worker } 237*c8dee2aaSAndroid Build Coastguard Worker // Reminder that DOMMatrix is column-major. 238*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[0] = matr['m11']; 239*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[1] = matr['m21']; 240*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[2] = matr['m41']; 241*c8dee2aaSAndroid Build Coastguard Worker 242*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[3] = matr['m12']; 243*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[4] = matr['m22']; 244*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[5] = matr['m42']; 245*c8dee2aaSAndroid Build Coastguard Worker 246*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[6] = matr['m14']; 247*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[7] = matr['m24']; 248*c8dee2aaSAndroid Build Coastguard Worker wasm3x3Matrix[8] = matr['m44']; 249*c8dee2aaSAndroid Build Coastguard Worker return _scratch3x3MatrixPtr; 250*c8dee2aaSAndroid Build Coastguard Worker} 251*c8dee2aaSAndroid Build Coastguard Worker 252*c8dee2aaSAndroid Build Coastguard Worker 253*c8dee2aaSAndroid Build Coastguard Worker// Copies the given DOMMatrix/Array/TypedArray to the CanvasKit heap and 254*c8dee2aaSAndroid Build Coastguard Worker// returns a pointer to the memory. This memory is a float* of length 16. 255*c8dee2aaSAndroid Build Coastguard Worker// If the passed in matrix is null/undefined, we return 0 (nullptr). The 256*c8dee2aaSAndroid Build Coastguard Worker// returned pointer should NOT be freed, as it is either null or a scratch 257*c8dee2aaSAndroid Build Coastguard Worker// pointer. 258*c8dee2aaSAndroid Build Coastguard Workerfunction copy4x4MatrixToWasm(matr) { 259*c8dee2aaSAndroid Build Coastguard Worker if (!matr) { 260*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 261*c8dee2aaSAndroid Build Coastguard Worker } 262*c8dee2aaSAndroid Build Coastguard Worker var wasm4x4Matrix = _scratch4x4Matrix['toTypedArray'](); 263*c8dee2aaSAndroid Build Coastguard Worker if (matr.length) { 264*c8dee2aaSAndroid Build Coastguard Worker if (matr.length !== 16 && matr.length !== 6 && matr.length !== 9) { 265*c8dee2aaSAndroid Build Coastguard Worker throw 'invalid matrix size'; 266*c8dee2aaSAndroid Build Coastguard Worker } 267*c8dee2aaSAndroid Build Coastguard Worker if (matr.length === 16) { 268*c8dee2aaSAndroid Build Coastguard Worker // matr should be an array or typed array. 269*c8dee2aaSAndroid Build Coastguard Worker return copy1dArray(matr, 'HEAPF32', _scratch4x4MatrixPtr); 270*c8dee2aaSAndroid Build Coastguard Worker } 271*c8dee2aaSAndroid Build Coastguard Worker // Upscale the row-major 3x3 or 3x2 matrix into a 4x4 row-major matrix 272*c8dee2aaSAndroid Build Coastguard Worker // TODO(skbug.com/10108) This will need to change when we convert our 273*c8dee2aaSAndroid Build Coastguard Worker // JS 4x4 to be column-major. 274*c8dee2aaSAndroid Build Coastguard Worker // When upscaling, we need to overwrite the 3rd column and the 3rd row with 275*c8dee2aaSAndroid Build Coastguard Worker // 0s. It's easiest to just do that with a fill command. 276*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix.fill(0); 277*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[0] = matr[0]; 278*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[1] = matr[1]; 279*c8dee2aaSAndroid Build Coastguard Worker // skip col 2 280*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[3] = matr[2]; 281*c8dee2aaSAndroid Build Coastguard Worker 282*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[4] = matr[3]; 283*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[5] = matr[4]; 284*c8dee2aaSAndroid Build Coastguard Worker // skip col 2 285*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[7] = matr[5]; 286*c8dee2aaSAndroid Build Coastguard Worker 287*c8dee2aaSAndroid Build Coastguard Worker // row2 == identity 288*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[10] = 1; 289*c8dee2aaSAndroid Build Coastguard Worker 290*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[12] = matr[6]; 291*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[13] = matr[7]; 292*c8dee2aaSAndroid Build Coastguard Worker // skip col 2 293*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[15] = matr[8]; 294*c8dee2aaSAndroid Build Coastguard Worker 295*c8dee2aaSAndroid Build Coastguard Worker if (matr.length === 6) { 296*c8dee2aaSAndroid Build Coastguard Worker // fix perspective for the 3x2 case (from above, they will be undefined). 297*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[12]=0; 298*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[13]=0; 299*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[15]=1; 300*c8dee2aaSAndroid Build Coastguard Worker } 301*c8dee2aaSAndroid Build Coastguard Worker return _scratch4x4MatrixPtr; 302*c8dee2aaSAndroid Build Coastguard Worker } else if (matr['m11'] === undefined) { 303*c8dee2aaSAndroid Build Coastguard Worker throw 'invalid matrix argument'; 304*c8dee2aaSAndroid Build Coastguard Worker } 305*c8dee2aaSAndroid Build Coastguard Worker // Reminder that DOMMatrix is column-major. 306*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[0] = matr['m11']; 307*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[1] = matr['m21']; 308*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[2] = matr['m31']; 309*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[3] = matr['m41']; 310*c8dee2aaSAndroid Build Coastguard Worker 311*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[4] = matr['m12']; 312*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[5] = matr['m22']; 313*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[6] = matr['m32']; 314*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[7] = matr['m42']; 315*c8dee2aaSAndroid Build Coastguard Worker 316*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[8] = matr['m13']; 317*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[9] = matr['m23']; 318*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[10] = matr['m33']; 319*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[11] = matr['m43']; 320*c8dee2aaSAndroid Build Coastguard Worker 321*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[12] = matr['m14']; 322*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[13] = matr['m24']; 323*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[14] = matr['m34']; 324*c8dee2aaSAndroid Build Coastguard Worker wasm4x4Matrix[15] = matr['m44']; 325*c8dee2aaSAndroid Build Coastguard Worker return _scratch4x4MatrixPtr; 326*c8dee2aaSAndroid Build Coastguard Worker} 327*c8dee2aaSAndroid Build Coastguard Worker 328*c8dee2aaSAndroid Build Coastguard Worker// copies a 4x4 matrix at the given pointer into a JS array. 329*c8dee2aaSAndroid Build Coastguard Workerfunction copy4x4MatrixFromWasm(matrPtr) { 330*c8dee2aaSAndroid Build Coastguard Worker // read them out into an array. TODO(kjlubick): If we change Matrix to be 331*c8dee2aaSAndroid Build Coastguard Worker // typedArrays, then we should return a typed array here too. 332*c8dee2aaSAndroid Build Coastguard Worker var rv = new Array(16); 333*c8dee2aaSAndroid Build Coastguard Worker for (var i = 0; i < 16; i++) { 334*c8dee2aaSAndroid Build Coastguard Worker rv[i] = CanvasKit.HEAPF32[matrPtr/4 + i]; // divide by 4 to cast to float. 335*c8dee2aaSAndroid Build Coastguard Worker } 336*c8dee2aaSAndroid Build Coastguard Worker return rv; 337*c8dee2aaSAndroid Build Coastguard Worker} 338*c8dee2aaSAndroid Build Coastguard Worker 339*c8dee2aaSAndroid Build Coastguard Worker// copies the given floats into the wasm heap as an SkColor4f. Unless a non-scratch pointer is 340*c8dee2aaSAndroid Build Coastguard Worker// passed into ptr, callers do NOT need to free the returned pointer. 341*c8dee2aaSAndroid Build Coastguard Workerfunction copyColorToWasm(color4f, ptr) { 342*c8dee2aaSAndroid Build Coastguard Worker return copy1dArray(color4f, 'HEAPF32', ptr || _scratchColorPtr); 343*c8dee2aaSAndroid Build Coastguard Worker} 344*c8dee2aaSAndroid Build Coastguard Worker 345*c8dee2aaSAndroid Build Coastguard Worker// copies the given color into the wasm heap. Callers do not need to free the returned pointer. 346*c8dee2aaSAndroid Build Coastguard Workerfunction copyColorComponentsToWasm(r, g, b, a) { 347*c8dee2aaSAndroid Build Coastguard Worker var colors = _scratchColor['toTypedArray'](); 348*c8dee2aaSAndroid Build Coastguard Worker colors[0] = r; 349*c8dee2aaSAndroid Build Coastguard Worker colors[1] = g; 350*c8dee2aaSAndroid Build Coastguard Worker colors[2] = b; 351*c8dee2aaSAndroid Build Coastguard Worker colors[3] = a; 352*c8dee2aaSAndroid Build Coastguard Worker return _scratchColorPtr; 353*c8dee2aaSAndroid Build Coastguard Worker} 354*c8dee2aaSAndroid Build Coastguard Worker 355*c8dee2aaSAndroid Build Coastguard Worker// copies the given color into the wasm heap. Callers must free the returned pointer. 356*c8dee2aaSAndroid Build Coastguard Workerfunction copyColorToWasmNoScratch(color4f) { 357*c8dee2aaSAndroid Build Coastguard Worker // TODO(kjlubick): accept 4 floats or int color 358*c8dee2aaSAndroid Build Coastguard Worker return copy1dArray(color4f, 'HEAPF32'); 359*c8dee2aaSAndroid Build Coastguard Worker} 360*c8dee2aaSAndroid Build Coastguard Worker 361*c8dee2aaSAndroid Build Coastguard Worker// copies the four floats at the given pointer in a js Float32Array 362*c8dee2aaSAndroid Build Coastguard Workerfunction copyColorFromWasm(colorPtr) { 363*c8dee2aaSAndroid Build Coastguard Worker var rv = new Float32Array(4); 364*c8dee2aaSAndroid Build Coastguard Worker for (var i = 0; i < 4; i++) { 365*c8dee2aaSAndroid Build Coastguard Worker rv[i] = CanvasKit.HEAPF32[colorPtr/4 + i]; // divide by 4 to cast to float. 366*c8dee2aaSAndroid Build Coastguard Worker } 367*c8dee2aaSAndroid Build Coastguard Worker return rv; 368*c8dee2aaSAndroid Build Coastguard Worker} 369*c8dee2aaSAndroid Build Coastguard Worker 370*c8dee2aaSAndroid Build Coastguard Worker// copies the given floats into the wasm heap as an SkRect. Unless a non-scratch pointer is 371*c8dee2aaSAndroid Build Coastguard Worker// passed into ptr, callers do NOT need to free the returned pointer. 372*c8dee2aaSAndroid Build Coastguard Workerfunction copyRectToWasm(fourFloats, ptr) { 373*c8dee2aaSAndroid Build Coastguard Worker return copy1dArray(fourFloats, 'HEAPF32', ptr || _scratchFourFloatsAPtr); 374*c8dee2aaSAndroid Build Coastguard Worker} 375*c8dee2aaSAndroid Build Coastguard Worker 376*c8dee2aaSAndroid Build Coastguard Worker// copies the given ints into the wasm heap as an SkIRect. Unless a non-scratch pointer is 377*c8dee2aaSAndroid Build Coastguard Worker// passed into ptr, callers do NOT need to free the returned pointer. 378*c8dee2aaSAndroid Build Coastguard Workerfunction copyIRectToWasm(fourInts, ptr) { 379*c8dee2aaSAndroid Build Coastguard Worker return copy1dArray(fourInts, 'HEAP32', ptr || _scratchIRectPtr); 380*c8dee2aaSAndroid Build Coastguard Worker} 381*c8dee2aaSAndroid Build Coastguard Worker 382*c8dee2aaSAndroid Build Coastguard Worker// copies the four ints at the given pointer into a JS Int32Array 383*c8dee2aaSAndroid Build Coastguard Workerfunction copyIRectFromWasm(rectMalloc, outputArray) { 384*c8dee2aaSAndroid Build Coastguard Worker var ta = rectMalloc['toTypedArray'](); 385*c8dee2aaSAndroid Build Coastguard Worker if (outputArray) { 386*c8dee2aaSAndroid Build Coastguard Worker outputArray.set(ta); 387*c8dee2aaSAndroid Build Coastguard Worker return outputArray; 388*c8dee2aaSAndroid Build Coastguard Worker } 389*c8dee2aaSAndroid Build Coastguard Worker return ta.slice(); 390*c8dee2aaSAndroid Build Coastguard Worker} 391*c8dee2aaSAndroid Build Coastguard Worker 392*c8dee2aaSAndroid Build Coastguard Worker// copies the given floats into the wasm heap as an SkRRect. Unless a non-scratch pointer is 393*c8dee2aaSAndroid Build Coastguard Worker// passed into ptr, callers do NOT need to free the returned pointer. 394*c8dee2aaSAndroid Build Coastguard Workerfunction copyRRectToWasm(twelveFloats, ptr) { 395*c8dee2aaSAndroid Build Coastguard Worker return copy1dArray(twelveFloats, 'HEAPF32', ptr || _scratchRRectPtr); 396*c8dee2aaSAndroid Build Coastguard Worker} 397