rsScriptC.cpp revision 1030893d9b99b72468034da13df025bda479bb97
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "rsContext.h" 18#include "rsScriptC.h" 19#include "rsMatrix.h" 20 21#include "acc/acc.h" 22 23using namespace android; 24using namespace android::renderscript; 25 26 27ScriptC::ScriptC() 28{ 29 mAccScript = NULL; 30 memset(&mProgram, 0, sizeof(mProgram)); 31} 32 33ScriptC::~ScriptC() 34{ 35 if (mAccScript) { 36 accDeleteScript(mAccScript); 37 } 38} 39 40extern "C" void matrixLoadIdentity(void *con, rsc_Matrix *mat) 41{ 42 Matrix *m = reinterpret_cast<Matrix *>(mat); 43 m->loadIdentity(); 44} 45 46extern "C" void matrixLoadFloat(void *con, rsc_Matrix *mat, const float *f) 47{ 48 Matrix *m = reinterpret_cast<Matrix *>(mat); 49 m->load(f); 50} 51 52extern "C" void matrixLoadMat(void *con, rsc_Matrix *mat, const rsc_Matrix *newmat) 53{ 54 Matrix *m = reinterpret_cast<Matrix *>(mat); 55 m->load(reinterpret_cast<const Matrix *>(newmat)); 56} 57 58extern "C" void matrixLoadRotate(void *con, rsc_Matrix *mat, float rot, float x, float y, float z) 59{ 60 Matrix *m = reinterpret_cast<Matrix *>(mat); 61 m->loadRotate(rot, x, y, z); 62} 63 64extern "C" void matrixLoadScale(void *con, rsc_Matrix *mat, float x, float y, float z) 65{ 66 Matrix *m = reinterpret_cast<Matrix *>(mat); 67 m->loadScale(x, y, z); 68} 69 70extern "C" void matrixLoadTranslate(void *con, rsc_Matrix *mat, float x, float y, float z) 71{ 72 Matrix *m = reinterpret_cast<Matrix *>(mat); 73 m->loadTranslate(x, y, z); 74} 75 76extern "C" void matrixLoadMultiply(void *con, rsc_Matrix *mat, const rsc_Matrix *lhs, const rsc_Matrix *rhs) 77{ 78 Matrix *m = reinterpret_cast<Matrix *>(mat); 79 m->loadMultiply(reinterpret_cast<const Matrix *>(lhs), 80 reinterpret_cast<const Matrix *>(rhs)); 81} 82 83extern "C" void matrixMultiply(void *con, rsc_Matrix *mat, const rsc_Matrix *rhs) 84{ 85 Matrix *m = reinterpret_cast<Matrix *>(mat); 86 m->multiply(reinterpret_cast<const Matrix *>(rhs)); 87} 88 89extern "C" void matrixRotate(void *con, rsc_Matrix *mat, float rot, float x, float y, float z) 90{ 91 Matrix *m = reinterpret_cast<Matrix *>(mat); 92 m->rotate(rot, x, y, z); 93} 94 95extern "C" void matrixScale(void *con, rsc_Matrix *mat, float x, float y, float z) 96{ 97 Matrix *m = reinterpret_cast<Matrix *>(mat); 98 m->scale(x, y, z); 99} 100 101extern "C" void matrixTranslate(void *con, rsc_Matrix *mat, float x, float y, float z) 102{ 103 Matrix *m = reinterpret_cast<Matrix *>(mat); 104 m->translate(x, y, z); 105} 106 107 108extern "C" const void * loadVp(void *vp, uint32_t bank, uint32_t offset) 109{ 110 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 111 return &static_cast<const uint8_t *>(env->mScript->mSlots[bank]->getPtr())[offset]; 112} 113 114extern "C" float loadF(void *vp, uint32_t bank, uint32_t offset) 115{ 116 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 117 //LOGE("bank %i, offset %i", bank, offset); 118 //LOGE("%p", env->mScript->mSlots[bank]->getPtr()); 119 return static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset]; 120} 121 122extern "C" int32_t loadI32(void *vp, uint32_t bank, uint32_t offset) 123{ 124 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 125 return static_cast<const int32_t *>(env->mScript->mSlots[bank]->getPtr())[offset]; 126} 127 128extern "C" uint32_t loadU32(void *vp, uint32_t bank, uint32_t offset) 129{ 130 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 131 return static_cast<const uint32_t *>(env->mScript->mSlots[bank]->getPtr())[offset]; 132} 133 134extern "C" void loadEnvVec4(void *vp, uint32_t bank, uint32_t offset, rsc_Vector4 *v) 135{ 136 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 137 memcpy(v, &static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset], sizeof(rsc_Vector4)); 138} 139 140extern "C" void loadEnvMatrix(void *vp, uint32_t bank, uint32_t offset, rsc_Matrix *m) 141{ 142 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 143 memcpy(m, &static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset], sizeof(rsc_Matrix)); 144} 145 146 147extern "C" void storeF(void *vp, uint32_t bank, uint32_t offset, float v) 148{ 149 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 150 static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset] = v; 151} 152 153extern "C" void storeI32(void *vp, uint32_t bank, uint32_t offset, int32_t v) 154{ 155 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 156 static_cast<int32_t *>(env->mScript->mSlots[bank]->getPtr())[offset] = v; 157} 158 159extern "C" void storeU32(void *vp, uint32_t bank, uint32_t offset, uint32_t v) 160{ 161 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 162 static_cast<uint32_t *>(env->mScript->mSlots[bank]->getPtr())[offset] = v; 163} 164 165extern "C" void storeEnvVec4(void *vp, uint32_t bank, uint32_t offset, const rsc_Vector4 *v) 166{ 167 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 168 memcpy(&static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset], v, sizeof(rsc_Vector4)); 169} 170 171extern "C" void storeEnvMatrix(void *vp, uint32_t bank, uint32_t offset, const rsc_Matrix *m) 172{ 173 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 174 memcpy(&static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset], m, sizeof(rsc_Matrix)); 175} 176 177 178extern "C" void color(void *vp, float r, float g, float b, float a) 179{ 180 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 181 glColor4f(r, g, b, a); 182} 183 184extern "C" void renderTriangleMesh(void *vp, RsTriangleMesh mesh) 185{ 186 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 187 rsi_TriangleMeshRender(env->mContext, mesh); 188} 189 190extern "C" void renderTriangleMeshRange(void *vp, RsTriangleMesh mesh, uint32_t start, uint32_t count) 191{ 192 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 193 rsi_TriangleMeshRenderRange(env->mContext, mesh, start, count); 194} 195 196extern "C" void materialDiffuse(void *vp, float r, float g, float b, float a) 197{ 198 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 199 float v[] = {r, g, b, a}; 200 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, v); 201} 202 203extern "C" void materialSpecular(void *vp, float r, float g, float b, float a) 204{ 205 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 206 float v[] = {r, g, b, a}; 207 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, v); 208} 209 210extern "C" void lightPosition(void *vp, float x, float y, float z, float w) 211{ 212 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 213 float v[] = {x, y, z, w}; 214 glLightfv(GL_LIGHT0, GL_POSITION, v); 215} 216 217extern "C" void materialShininess(void *vp, float s) 218{ 219 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 220 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &s); 221} 222 223extern "C" void uploadToTexture(void *vp, RsAllocation va, uint32_t baseMipLevel) 224{ 225 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 226 rsi_AllocationUploadToTexture(env->mContext, va, baseMipLevel); 227} 228 229extern "C" void enable(void *vp, uint32_t p) 230{ 231 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 232 glEnable(p); 233} 234 235extern "C" void disable(void *vp, uint32_t p) 236{ 237 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 238 glDisable(p); 239} 240 241extern "C" uint32_t scriptRand(void *vp, uint32_t max) 242{ 243 return (uint32_t)(((float)rand()) * max / RAND_MAX); 244} 245 246// Assumes (GL_FIXED) x,y,z (GL_UNSIGNED_BYTE)r,g,b,a 247extern "C" void drawTriangleArray(void *vp, RsAllocation alloc, uint32_t count) 248{ 249 const Allocation *a = (const Allocation *)alloc; 250 const uint32_t *ptr = (const uint32_t *)a->getPtr(); 251 252 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 253 env->mContext->setupCheck(); 254 255 glBindBuffer(GL_ARRAY_BUFFER, 0); 256 //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]); 257 258 glEnableClientState(GL_VERTEX_ARRAY); 259 glDisableClientState(GL_NORMAL_ARRAY); 260 glDisableClientState(GL_TEXTURE_COORD_ARRAY); 261 glEnableClientState(GL_COLOR_ARRAY); 262 263 glVertexPointer(2, GL_FIXED, 12, ptr + 1); 264 //glTexCoordPointer(2, GL_FIXED, 24, ptr + 1); 265 glColorPointer(4, GL_UNSIGNED_BYTE, 12, ptr); 266 267 glDrawArrays(GL_TRIANGLES, 0, count * 3); 268} 269 270extern "C" void drawRect(void *vp, int32_t x1, int32_t x2, int32_t y1, int32_t y2) 271{ 272 x1 = (x1 << 16); 273 x2 = (x2 << 16); 274 y1 = (y1 << 16); 275 y2 = (y2 << 16); 276 277 int32_t vtx[] = {x1,y1, x1,y2, x2,y1, x2,y2}; 278 static const int32_t tex[] = {0,0, 0,0x10000, 0x10000,0, 0x10000,0x10000}; 279 280 281 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 282 env->mContext->setupCheck(); 283 284 glBindBuffer(GL_ARRAY_BUFFER, 0); 285 //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]); 286 287 glEnableClientState(GL_VERTEX_ARRAY); 288 glEnableClientState(GL_TEXTURE_COORD_ARRAY); 289 glDisableClientState(GL_NORMAL_ARRAY); 290 glDisableClientState(GL_COLOR_ARRAY); 291 292 glVertexPointer(2, GL_FIXED, 8, vtx); 293 glTexCoordPointer(2, GL_FIXED, 8, tex); 294 //glColorPointer(4, GL_UNSIGNED_BYTE, 12, ptr); 295 296 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 297} 298 299extern "C" void pfBindTexture(void *vp, RsProgramFragment vpf, uint32_t slot, RsAllocation va) 300{ 301 //LOGE("pfBindTexture %p", vpf); 302 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 303 rsi_ProgramFragmentBindTexture(env->mContext, 304 static_cast<ProgramFragment *>(vpf), 305 slot, 306 static_cast<Allocation *>(va)); 307 308} 309 310extern "C" void pfBindSampler(void *vp, RsProgramFragment vpf, uint32_t slot, RsSampler vs) 311{ 312 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 313 rsi_ProgramFragmentBindSampler(env->mContext, 314 static_cast<ProgramFragment *>(vpf), 315 slot, 316 static_cast<Sampler *>(vs)); 317 318} 319 320extern "C" void contextBindProgramFragmentStore(void *vp, RsProgramFragmentStore pfs) 321{ 322 //LOGE("contextBindProgramFragmentStore %p", pfs); 323 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 324 rsi_ContextBindProgramFragmentStore(env->mContext, pfs); 325 326} 327 328extern "C" void contextBindProgramFragment(void *vp, RsProgramFragment pf) 329{ 330 //LOGE("contextBindProgramFragment %p", pf); 331 ScriptC::Env * env = static_cast<ScriptC::Env *>(vp); 332 rsi_ContextBindProgramFragment(env->mContext, pf); 333 334} 335 336 337static rsc_FunctionTable scriptCPtrTable = { 338 loadVp, 339 loadF, 340 loadI32, 341 loadU32, 342 loadEnvVec4, 343 loadEnvMatrix, 344 345 storeF, 346 storeI32, 347 storeU32, 348 storeEnvVec4, 349 storeEnvMatrix, 350 351 matrixLoadIdentity, 352 matrixLoadFloat, 353 matrixLoadMat, 354 matrixLoadRotate, 355 matrixLoadScale, 356 matrixLoadTranslate, 357 matrixLoadMultiply, 358 matrixMultiply, 359 matrixRotate, 360 matrixScale, 361 matrixTranslate, 362 363 color, 364 365 pfBindTexture, 366 pfBindSampler, 367 368 materialDiffuse, 369 materialSpecular, 370 lightPosition, 371 materialShininess, 372 uploadToTexture, 373 enable, 374 disable, 375 376 scriptRand, 377 contextBindProgramFragment, 378 contextBindProgramFragmentStore, 379 380 381 renderTriangleMesh, 382 renderTriangleMeshRange, 383 384 drawTriangleArray, 385 drawRect 386 387}; 388 389 390bool ScriptC::run(Context *rsc, uint32_t launchID) 391{ 392 Env e = {rsc, this}; 393 return mProgram.mScript(&e, &scriptCPtrTable, launchID) != 0; 394} 395 396ScriptCState::ScriptCState() 397{ 398 clear(); 399} 400 401ScriptCState::~ScriptCState() 402{ 403 if (mAccScript) { 404 accDeleteScript(mAccScript); 405 } 406} 407 408void ScriptCState::clear() 409{ 410 memset(&mProgram, 0, sizeof(mProgram)); 411 412 mConstantBufferTypes.clear(); 413 414 memset(&mEnviroment, 0, sizeof(mEnviroment)); 415 mEnviroment.mClearColor[0] = 0; 416 mEnviroment.mClearColor[1] = 0; 417 mEnviroment.mClearColor[2] = 0; 418 mEnviroment.mClearColor[3] = 1; 419 mEnviroment.mClearDepth = 1; 420 mEnviroment.mClearStencil = 0; 421 mEnviroment.mIsRoot = false; 422 mEnviroment.mIsOrtho = true; 423 424 mAccScript = NULL; 425 426} 427 428void ScriptCState::runCompiler() 429{ 430 mAccScript = accCreateScript(); 431 432 const char* scriptSource[] = {mProgram.mScriptText}; 433 int scriptLength[] = {mProgram.mScriptTextLength} ; 434 accScriptSource(mAccScript, 1, scriptSource, scriptLength); 435 accCompileScript(mAccScript); 436 accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript); 437 rsAssert(mProgram.mScript); 438 439 if (mProgram.mScript) { 440 const static int pragmaMax = 16; 441 ACCsizei pragmaCount; 442 ACCchar * str[pragmaMax]; 443 accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]); 444 445 // Start with defaults 446 mEnviroment.mStateVertex = 447 Script::Enviroment_t::VTX_ORTHO_WINDOW; 448 mEnviroment.mStateRaster = 449 Script::Enviroment_t::RASTER_FLAT; 450 mEnviroment.mStateFragment = 451 Script::Enviroment_t::FRAGMENT_COLOR; 452 mEnviroment.mStateFragmentStore = 453 Script::Enviroment_t::FRAGMENT_STORE_ALWAYS_REPLACE; 454 455 for (int ct=0; ct < pragmaCount; ct+=2) { 456 LOGE("pragma %i %s %s", ct, str[ct], str[ct+1]); 457 458 if (!strcmp(str[ct], "version")) { 459 continue; 460 461 } 462 463 464 if (!strcmp(str[ct], "stateVertex")) { 465 if (!strcmp(str[ct+1], "orthoWindow")) { 466 mEnviroment.mStateVertex = 467 Script::Enviroment_t::VTX_ORTHO_WINDOW; 468 continue; 469 } 470 if (!strcmp(str[ct+1], "orthoNormalized")) { 471 mEnviroment.mStateVertex = 472 Script::Enviroment_t::VTX_ORTHO_NORMALIZED; 473 continue; 474 } 475 if (!strcmp(str[ct+1], "projection")) { 476 mEnviroment.mStateVertex = 477 Script::Enviroment_t::VTX_PROJECTION; 478 continue; 479 } 480 if (!strcmp(str[ct+1], "parent")) { 481 mEnviroment.mStateVertex = 482 Script::Enviroment_t::VTX_PARENT; 483 continue; 484 } 485 LOGE("Unreconized value %s passed to stateVertex", str[ct+1]); 486 } 487 488 if (!strcmp(str[ct], "stateRaster")) { 489 if (!strcmp(str[ct+1], "flat")) { 490 mEnviroment.mStateRaster = 491 Script::Enviroment_t::RASTER_FLAT; 492 continue; 493 } 494 if (!strcmp(str[ct+1], "smooth")) { 495 mEnviroment.mStateRaster = 496 Script::Enviroment_t::RASTER_SMOOTH; 497 continue; 498 } 499 if (!strcmp(str[ct+1], "parent")) { 500 mEnviroment.mStateRaster = 501 Script::Enviroment_t::RASTER_PARENT; 502 continue; 503 } 504 LOGE("Unreconized value %s passed to stateRaster", str[ct+1]); 505 } 506 507 if (!strcmp(str[ct], "stateFragment")) { 508 if (!strcmp(str[ct+1], "color")) { 509 mEnviroment.mStateFragment = 510 Script::Enviroment_t::FRAGMENT_COLOR; 511 continue; 512 } 513 if (!strcmp(str[ct+1], "texReplace")) { 514 mEnviroment.mStateFragment = 515 Script::Enviroment_t::FRAGMENT_TEX_REPLACE; 516 continue; 517 } 518 if (!strcmp(str[ct+1], "texModulate")) { 519 mEnviroment.mStateFragment = 520 Script::Enviroment_t::FRAGMENT_TEX_MODULATE; 521 continue; 522 } 523 if (!strcmp(str[ct+1], "parent")) { 524 mEnviroment.mStateFragment = 525 Script::Enviroment_t::FRAGMENT_PARENT; 526 continue; 527 } 528 LOGE("Unreconized value %s passed to stateFragment", str[ct+1]); 529 } 530 531 if (!strcmp(str[ct], "stateFragmentStore")) { 532 if (!strcmp(str[ct+1], "alwaysReplace")) { 533 mEnviroment.mStateFragmentStore = 534 Script::Enviroment_t::FRAGMENT_STORE_ALWAYS_REPLACE; 535 continue; 536 } 537 if (!strcmp(str[ct+1], "alwaysBlend")) { 538 mEnviroment.mStateFragmentStore = 539 Script::Enviroment_t::FRAGMENT_STORE_ALWAYS_BLEND; 540 continue; 541 } 542 if (!strcmp(str[ct+1], "depthLessReplace")) { 543 mEnviroment.mStateFragmentStore = 544 Script::Enviroment_t::FRAGMENT_STORE_DEPTH_LESS_REPLACE; 545 continue; 546 } 547 if (!strcmp(str[ct+1], "depthLessBlend")) { 548 mEnviroment.mStateFragmentStore = 549 Script::Enviroment_t::FRAGMENT_STORE_DEPTH_LESS_BLEND; 550 continue; 551 } 552 if (!strcmp(str[ct+1], "parent")) { 553 mEnviroment.mStateFragmentStore = 554 Script::Enviroment_t::FRAGMENT_STORE_PARENT; 555 continue; 556 } 557 LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]); 558 } 559 560 } 561 562 563 } else { 564 // Deal with an error. 565 } 566 567} 568 569namespace android { 570namespace renderscript { 571 572void rsi_ScriptCBegin(Context * rsc) 573{ 574 ScriptCState *ss = &rsc->mScriptC; 575 ss->clear(); 576} 577 578void rsi_ScriptCSetClearColor(Context * rsc, float r, float g, float b, float a) 579{ 580 ScriptCState *ss = &rsc->mScriptC; 581 ss->mEnviroment.mClearColor[0] = r; 582 ss->mEnviroment.mClearColor[1] = g; 583 ss->mEnviroment.mClearColor[2] = b; 584 ss->mEnviroment.mClearColor[3] = a; 585} 586 587void rsi_ScriptCSetClearDepth(Context * rsc, float v) 588{ 589 ScriptCState *ss = &rsc->mScriptC; 590 ss->mEnviroment.mClearDepth = v; 591} 592 593void rsi_ScriptCSetClearStencil(Context * rsc, uint32_t v) 594{ 595 ScriptCState *ss = &rsc->mScriptC; 596 ss->mEnviroment.mClearStencil = v; 597} 598 599void rsi_ScriptCAddType(Context * rsc, RsType vt) 600{ 601 ScriptCState *ss = &rsc->mScriptC; 602 ss->mConstantBufferTypes.add(static_cast<const Type *>(vt)); 603} 604 605void rsi_ScriptCSetScript(Context * rsc, void *vp) 606{ 607 ScriptCState *ss = &rsc->mScriptC; 608 ss->mProgram.mScript = reinterpret_cast<rsc_RunScript>(vp); 609} 610 611void rsi_ScriptCSetRoot(Context * rsc, bool isRoot) 612{ 613 ScriptCState *ss = &rsc->mScriptC; 614 ss->mEnviroment.mIsRoot = isRoot; 615} 616 617void rsi_ScriptCSetOrtho(Context * rsc, bool isOrtho) 618{ 619 ScriptCState *ss = &rsc->mScriptC; 620 ss->mEnviroment.mIsOrtho = isOrtho; 621} 622 623void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) 624{ 625 ScriptCState *ss = &rsc->mScriptC; 626 ss->mProgram.mScriptText = text; 627 ss->mProgram.mScriptTextLength = len; 628} 629 630 631RsScript rsi_ScriptCCreate(Context * rsc) 632{ 633 ScriptCState *ss = &rsc->mScriptC; 634 635 ss->runCompiler(); 636 637 ScriptC *s = new ScriptC(); 638 s->incRef(); 639 s->mAccScript = ss->mAccScript; 640 ss->mAccScript = NULL; 641 s->mEnviroment = ss->mEnviroment; 642 s->mProgram = ss->mProgram; 643 ss->clear(); 644 645 return s; 646} 647 648} 649} 650 651 652