rsAdapter.cpp revision e514b45de8561fbc6ef6770845102ca10b0a69d7
1326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 2326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams/* 3326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Copyright (C) 2009 The Android Open Source Project 4326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * 5326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 6326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * you may not use this file except in compliance with the License. 7326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * You may obtain a copy of the License at 8326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * 9326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * http://www.apache.org/licenses/LICENSE-2.0 10326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * 11326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Unless required by applicable law or agreed to in writing, software 12326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * distributed under the License is distributed on an "AS IS" BASIS, 13326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * See the License for the specific language governing permissions and 15326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * limitations under the License. 16326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams */ 17326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 18326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "rsContext.h" 19326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 20326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsusing namespace android; 21326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsusing namespace android::renderscript; 22326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 23326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 24e514b45de8561fbc6ef6770845102ca10b0a69d7Jason SamsAdapter1D::Adapter1D(Context *rsc) : ObjectBase(rsc) 25326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 26326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams reset(); 27326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 28326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 29e514b45de8561fbc6ef6770845102ca10b0a69d7Jason SamsAdapter1D::Adapter1D(Context *rsc, Allocation *a) : ObjectBase(rsc) 30326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 31326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams reset(); 32326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams setAllocation(a); 33326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 34326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 35326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid Adapter1D::reset() 36326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 37326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mY = 0; 38326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mZ = 0; 39326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mLOD = 0; 40326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mFace = 0; 41326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 42326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 43326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid * Adapter1D::getElement(uint32_t x) 44326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 45326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation.get()); 46326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation->getPtr()); 47326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation->getType()); 48326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams uint8_t * ptr = static_cast<uint8_t *>(mAllocation->getPtr()); 49326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams ptr += mAllocation->getType()->getLODOffset(mLOD, x, mY); 50326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return ptr; 51326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 52326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 53326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid Adapter1D::subData(uint32_t xoff, uint32_t count, const void *data) 54326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 55326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams if (mAllocation.get() && mAllocation.get()->getType()) { 56326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams void *ptr = getElement(xoff); 57326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams count *= mAllocation.get()->getType()->getElementSizeBytes(); 58326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams memcpy(ptr, data, count); 59326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 60326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 61326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 62326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid Adapter1D::data(const void *data) 63326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 64d3c8de2efc8f4f9287e0a8dfdeefb03ba6aaec98Jason Sams memcpy(getElement(0), 65d3c8de2efc8f4f9287e0a8dfdeefb03ba6aaec98Jason Sams data, 66326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mAllocation.get()->getType()->getSizeBytes()); 67326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 68326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 69326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace android { 70326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace renderscript { 71326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 72326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsRsAdapter1D rsi_Adapter1DCreate(Context *rsc) 73326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 74e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams Adapter1D *a = new Adapter1D(rsc); 759397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams a->incUserRef(); 76d3c8de2efc8f4f9287e0a8dfdeefb03ba6aaec98Jason Sams return a; 77326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 78326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 79326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter1DBindAllocation(Context *rsc, RsAdapter1D va, RsAllocation valloc) 80326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 81326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter1D * a = static_cast<Adapter1D *>(va); 82326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Allocation * alloc = static_cast<Allocation *>(valloc); 83326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setAllocation(alloc); 84326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 85326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 86326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter1DSetConstraint(Context *rsc, RsAdapter1D va, RsDimension dim, uint32_t value) 87326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 88326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter1D * a = static_cast<Adapter1D *>(va); 89326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams switch(dim) { 90326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_X: 91326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(!"Cannot contrain X in an 1D adapter"); 92326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return; 93326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_Y: 94326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setY(value); 95326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 96326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_Z: 97326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setZ(value); 98326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 99326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_LOD: 100326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setLOD(value); 101326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 102326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_FACE: 103326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setFace(value); 104326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 105326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams default: 106326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(!"Unimplemented constraint"); 107326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return; 108326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 109326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 110326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 111326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter1DSubData(Context *rsc, RsAdapter1D va, uint32_t xoff, uint32_t count, const void *data) 112326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 113326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter1D * a = static_cast<Adapter1D *>(va); 114326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->subData(xoff, count, data); 115326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 116326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 117326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter1DData(Context *rsc, RsAdapter1D va, const void *data) 118326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 119326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter1D * a = static_cast<Adapter1D *>(va); 120326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->data(data); 121326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 122326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 123326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 124326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 125326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 126326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams////////////////////////// 127326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 128e514b45de8561fbc6ef6770845102ca10b0a69d7Jason SamsAdapter2D::Adapter2D(Context *rsc) : ObjectBase(rsc) 129326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 130326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams reset(); 131326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 132326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 133e514b45de8561fbc6ef6770845102ca10b0a69d7Jason SamsAdapter2D::Adapter2D(Context *rsc, Allocation *a) : ObjectBase(rsc) 134326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 135326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams reset(); 136326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams setAllocation(a); 137326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 138326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 139326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid Adapter2D::reset() 140326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 141326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mZ = 0; 142326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mLOD = 0; 143326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mFace = 0; 144326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 145326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 146326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid * Adapter2D::getElement(uint32_t x, uint32_t y) const 147326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 148326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation.get()); 149326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation->getPtr()); 150326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation->getType()); 151326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams uint8_t * ptr = static_cast<uint8_t *>(mAllocation->getPtr()); 152326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams ptr += mAllocation->getType()->getLODOffset(mLOD, x, y); 153326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return ptr; 154326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 155326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 156326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid Adapter2D::subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) 157326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 158326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation.get()); 159326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation->getPtr()); 160326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(mAllocation->getType()); 161326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 162326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams uint32_t eSize = mAllocation.get()->getType()->getElementSizeBytes(); 163326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams uint32_t lineSize = eSize * w; 164326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams uint32_t destW = getDimX(); 165326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 166326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams const uint8_t *src = static_cast<const uint8_t *>(data); 167326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams for (uint32_t line=yoff; line < (yoff+h); line++) { 168326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams memcpy(getElement(xoff, line), src, lineSize); 169326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams src += lineSize; 170326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 171326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 172326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 173326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid Adapter2D::data(const void *data) 174326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 175d3c8de2efc8f4f9287e0a8dfdeefb03ba6aaec98Jason Sams memcpy(getElement(0,0), 176d3c8de2efc8f4f9287e0a8dfdeefb03ba6aaec98Jason Sams data, 177326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams mAllocation.get()->getType()->getSizeBytes()); 178326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 179326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 180326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 181326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 182326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace android { 183326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsnamespace renderscript { 184326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 185326e0ddf89e8df2837752fbfd7a014814b32082cJason SamsRsAdapter2D rsi_Adapter2DCreate(Context *rsc) 186326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 187e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams Adapter2D *a = new Adapter2D(rsc); 1889397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams a->incUserRef(); 189d3c8de2efc8f4f9287e0a8dfdeefb03ba6aaec98Jason Sams return a; 190326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 191326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 192326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter2DBindAllocation(Context *rsc, RsAdapter2D va, RsAllocation valloc) 193326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 194326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter2D * a = static_cast<Adapter2D *>(va); 195326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Allocation * alloc = static_cast<Allocation *>(valloc); 196326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setAllocation(alloc); 197326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 198326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 199326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter2DSetConstraint(Context *rsc, RsAdapter2D va, RsDimension dim, uint32_t value) 200326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 201326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter2D * a = static_cast<Adapter2D *>(va); 202326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams switch(dim) { 203326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_X: 204326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(!"Cannot contrain X in an 2D adapter"); 205326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return; 206326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_Y: 207326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(!"Cannot contrain Y in an 2D adapter"); 208326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 209326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_Z: 210326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setZ(value); 211326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 212326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_LOD: 213326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setLOD(value); 214326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 215326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams case RS_DIMENSION_FACE: 216326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->setFace(value); 217326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams break; 218326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams default: 219326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams rsAssert(!"Unimplemented constraint"); 220326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams return; 221326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams } 222326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 223326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 224326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter2DData(Context *rsc, RsAdapter2D va, const void *data) 225326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 226326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter2D * a = static_cast<Adapter2D *>(va); 227326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->data(data); 228326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 229326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 230326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid rsi_Adapter2DSubData(Context *rsc, RsAdapter2D va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) 231326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{ 232326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams Adapter2D * a = static_cast<Adapter2D *>(va); 233326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams a->subData(xoff, yoff, w, h, data); 234326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 235326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams 236326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 237326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams} 238